diff --git a/doc/history/2026-09-14-7차.md b/doc/history/2026-09-14-7차.md
index 8bdab70..a4f92ac 100644
--- a/doc/history/2026-09-14-7차.md
+++ b/doc/history/2026-09-14-7차.md
@@ -45,6 +45,39 @@ MergeHub 파일 비교 탭에서 그 파일의 충돌 6개를 Take Theirs → [S
MergeSaveTest 70건 통과. 빌드 경고 0 · 오류 0. 설정 파일은 바이트 그대로 되돌림.
+## E-2. 폴더 비교 탭에 폴더를 하나씩 끌어다 놓으면 첫 칸 → 둘째 칸 차례로 (2026-09-14, 추가 요청, 완료)
+
+사용자: "폴더비교 탭 첫번째 드래그 첫번째 폴더 경로에 들어가고 두번째는 드래그앤드롭은 두번째로 들어가게해줘 경로텍스트 박스에 안넣어도 그냥 화면에다 넣어둬 기능 동작하도록".
+
+### 원인 (코드로 확인)
+
+- 화면 아무 데나 놓으면 `FolderView.View_Drop` → `GitWorkspace.RouteDroppedPaths` → `RequestFolderCompare(왼쪽, null)`. **폴더 하나는 늘 첫 칸**으로 갔다.
+ 두 번째 폴더를 놓아도 첫 칸을 덮어써서, 경로 칸 위에 정확히 놓지 않으면 두 폴더를 견줄 수 없었다.
+- 경로 칸 위에 놓는 길(`PreviewDrop` → `DropIntoSlot`)은 그 칸에 제대로 들어갔다.
+- 고치기 전 모습은 화면으로 따로 찍지 않았다 — 위 경로를 코드로 따라가 확인했다.
+
+### 고친 것
+
+| 파일 | 무엇 |
+|---|---|
+| `Services/DropSlotOrder.cs` (새 파일) | 놓는 차례. `Take()` 는 첫 칸 → 둘째 칸 → 첫 칸 … 을 주고, `Placed(칸)` 은 칸에 바로 놓은 것도 차례에 쳐서 다음을 반대 칸으로 |
+| `Views/FolderView.xaml.cs` | 화면에 **폴더 하나**를 놓으면 `DropFolder(폴더, 차례 칸)` — 양쪽이 차면 바로 견준다(원래 있던 동작). 경로 칸 위에 놓으면 그 칸에 넣고 차례를 넘김(두 개를 한꺼번에 놓아 양쪽을 채웠으면 다음은 첫 칸). 두 개 · 파일을 놓는 길은 그대로(명령줄과 같은 판단) |
+| 하네스 `PathTest` | 차례 검사 8건 |
+
+### 확인한 것 (실제 탐색기 창에서 마우스로 끌어다 놓기)
+
+경로 칸을 비우고, 탐색기에서 폴더를 끌어 **폴더 비교 화면의 빈 곳**(경로 칸이 아닌 곳)에 놓았다.
+
+| # | 놓은 것 · 자리 | 첫 칸 | 둘째 칸 |
+|---|---|---|---|
+| 1 | `왼쪽폴더` · 화면 | **왼쪽폴더** | (빔) |
+| 2 | `오른쪽폴더` · 화면 | 왼쪽폴더 | **오른쪽폴더** — 바로 비교, 결과에 `a.txt` |
+| 3 | `세번째폴더` · 화면 | **세번째폴더** | 오른쪽폴더 |
+| 4 | `왼쪽폴더` · **둘째 경로 칸 위** | 세번째폴더 | **왼쪽폴더** |
+| 5 | `오른쪽폴더` · 화면 (차례: 첫 칸) | **오른쪽폴더** | 왼쪽폴더 |
+
+PathTest 62건 통과. 빌드 경고 0 · 오류 0.
+
## E-3. 사용자 이름을 저장하기 전에는 화면을 쓸 수 없게 (2026-09-14, 추가 요청, 완료)
사용자: "사용자 이름을 저장하고 화면이 움직이거나 바뀌도록 잠궈야해". 저장해야만 화면을 움직이거나 바꿀 수 있게 잠근다고 읽었다.
diff --git a/doc/history/changelog.md b/doc/history/changelog.md
index e70a802..85ae6ab 100644
--- a/doc/history/changelog.md
+++ b/doc/history/changelog.md
@@ -8,6 +8,7 @@
| 날짜 | 항목 | 커밋 |
|---|---|---|
+| 2026-09-14 | **7차 E-2** — 폴더 비교 화면 아무 데나 폴더를 하나 놓으면 늘 첫 칸에 들어가 두 번째 폴더가 첫 폴더를 덮어썼다. 놓는 차례대로 첫 칸 → 둘째 칸(양쪽이 차면 바로 비교), 경로 칸 위에 놓은 것도 차례에 친다. 탐색기에서 끌어다 놓아 확인 | 아래 |
| 2026-09-14 | **7차 E-3** — 켤 때 사용자 이름 창을 Alt+F4 로 닫으면 이름 없이 본 창을 쓸 수 있었고 창도 끌려 움직였다. 저장 전에는 닫히지 않고 움직이지 않게(플랫폼 `UserNameDialog`, 확인 받고 `D:\UbisamPlatform\bin` 배포). MergeHub 코드 변경 없음 | 아래 |
| 2026-09-14 | **7차 A-1** — 마지막 충돌을 [Save] 하면 파일 비교 탭이 "남은 차이 6줄" 로 떨어져 덜 푼 것처럼 보이던 것. 병합 중 충돌 0 이면 두 칸 요약이 "충돌 정리 끝 · 병합 커밋을 할 수 있습니다 · 내 쪽 대비 받은 변경 N줄", BASE 제목에 "병합 전 내 쪽". E-1 때 못 돌린 MergeSaveTest 기대값도 [Save] 로 | 아래 |
| 2026-09-14 | **7차 지시서 · E-1** — 6차 D-1 에서 걸린 세 가지와 pull · rebase · cherry-pick 충돌로 7차 지시서를 씀. 병합 중 [해결로 저장] 단추를 [Save] 로(LOCAL 저장 단추라 Save & Commit 과 짝). 하는 일 그대로, 알림 · 막힘 안내 · 웹 문서 이름도 | 아래 |
diff --git a/doc/진행상황.md b/doc/진행상황.md
index b857f2d..94dd3c4 100644
--- a/doc/진행상황.md
+++ b/doc/진행상황.md
@@ -177,7 +177,7 @@
| 상태 | 항목 |
|---|---|
| **완료** | E-1 [해결로 저장] 이름을 [Save] 로 — 하는 일은 그대로, 알림 · 안내 · 웹 문서 이름도 |
-| 진행 | E-2 폴더 비교 탭에 폴더를 하나씩 끌어다 놓으면 첫 칸 → 둘째 칸 차례로 (경로 칸 위가 아니어도) |
+| **완료** | E-2 폴더 비교 탭에 폴더를 하나씩 끌어다 놓으면 첫 칸 → 둘째 칸 차례로 (경로 칸 위가 아니어도) — 양쪽이 차면 바로 비교, 칸 위에 놓은 것도 차례에 침 |
| **완료** | E-3 사용자 이름을 저장하기 전에는 화면을 쓸 수 없게 — 이름 창이 끌어도 안 움직이고 저장 없이 닫히지 않음(플랫폼, 배포함) |
---
diff --git a/src/MergeHub/Services/DropSlotOrder.cs b/src/MergeHub/Services/DropSlotOrder.cs
new file mode 100644
index 0000000..ddd44aa
--- /dev/null
+++ b/src/MergeHub/Services/DropSlotOrder.cs
@@ -0,0 +1,27 @@
+namespace MergeHub.Services
+{
+ ///
+ /// 폴더 비교 화면에 폴더를 하나씩 끌어다 놓을 때 어느 칸에 넣을지 정한다(7차 E-2).
+ ///
+ /// 예전에는 화면 아무 데나 폴더 하나를 놓으면 늘 첫 번째 칸에 들어갔다. 두 번째 폴더를 놓아도
+ /// 첫 칸을 덮어써서 경로 칸 위에 정확히 놓지 않으면 두 폴더를 견줄 수 없었다.
+ /// 이제 놓는 차례대로 첫 칸 → 둘째 칸 → 첫 칸 … 으로 들어간다.
+ /// 경로 칸 위에 바로 놓은 것도 차례에 친다 - 둘째 칸에 놓았으면 다음은 첫 칸이다.
+ ///
+ public sealed class DropSlotOrder
+ {
+ /// 다음에 화면에 놓을 폴더가 첫 칸으로 가는지.
+ public bool NextIsLeft { get; private set; } = true;
+
+ /// 화면 아무 데나 놓았을 때 - 차례의 칸을 주고 차례를 넘긴다.
+ public bool Take()
+ {
+ var left = NextIsLeft;
+ NextIsLeft = !left;
+ return left;
+ }
+
+ /// 경로 칸 위에 바로 놓았을 때 - 그 칸에 들어갔으니 다음은 반대 칸이다.
+ public void Placed(bool left) => NextIsLeft = !left;
+ }
+}
diff --git a/src/MergeHub/Views/FolderView.xaml.cs b/src/MergeHub/Views/FolderView.xaml.cs
index 530795a..162d537 100644
--- a/src/MergeHub/Views/FolderView.xaml.cs
+++ b/src/MergeHub/Views/FolderView.xaml.cs
@@ -136,10 +136,16 @@ namespace MergeHub.Views
private void View_DragOver(object sender, DragEventArgs e) => AllowFileDrop(e);
+ /// 놓는 차례대로 첫 칸 · 둘째 칸에 넣는다(7차 E-2).
+ private readonly Services.DropSlotOrder _dropOrder = new Services.DropSlotOrder();
+
///
/// 화면 아무 데나 놓았을 때. 두 개를 놓으면 양쪽에 하나씩 들어간다.
///
- /// 판단은 명령줄로 들어오는 길과 같은 것을 쓴다 - 폴더면 폴더 비교, 파일이면 파일 비교로
+ /// 폴더 하나를 놓으면 차례대로 첫 칸 → 둘째 칸에 들어간다. 경로 칸 위에 정확히 놓지 않아도 된다(7차 E-2).
+ /// 예전에는 늘 첫 칸에 들어가 두 번째 폴더가 첫 폴더를 덮어썼다. 양쪽이 차면 바로 견준다.
+ ///
+ /// 그 밖(두 개 · 파일)은 명령줄로 들어오는 길과 같은 판단을 쓴다 - 폴더면 폴더 비교, 파일이면 파일 비교로
/// 탭까지 옮긴다. 폴더 화면에 파일을 놓았다고 아무 일도 안 하는 것은 불친절하다.
///
private void View_Drop(object sender, DragEventArgs e)
@@ -147,6 +153,13 @@ namespace MergeHub.Views
if (DataContext is not FolderViewModel vm) return;
if (DroppedPaths(e) is not { Length: > 0 } paths) return;
+ if (paths.Length == 1 && System.IO.Directory.Exists(paths[0]))
+ {
+ vm.DropFolder(Services.PathUtil.FullFolderPath(paths[0]), _dropOrder.Take());
+ e.Handled = true;
+ return;
+ }
+
vm.Workspace.RouteDroppedPaths(paths);
e.Handled = true;
}
@@ -190,6 +203,10 @@ namespace MergeHub.Views
// 넣고 나서 양쪽이 다 찼으면 그 자리에서 견준다.
vm.DropFolder(folder, left);
+ // 칸에 바로 놓은 것도 차례에 친다 - 다음에 화면에 놓는 폴더는 반대 칸으로 간다.
+ // 두 개를 한꺼번에 놓아 양쪽을 다 채웠으면 다음은 첫 칸부터다.
+ _dropOrder.Placed(paths.Length > 1 ? false : left);
+
e.Handled = true;
}