Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4d8a1f5
refactor: DI 적용 및 Repository 패턴 도입
1hyok Nov 12, 2025
fb67908
refactor: ViewModel 분리 및 Repository 패턴 적용
1hyok Nov 12, 2025
b801059
refactor: ViewModel 분리 및 UI 상태 관리 개선
1hyok Nov 13, 2025
ba74537
refactor: ViewModel 팩토리 및 게시글 목록 새로고침 로직 개선
1hyok Nov 13, 2025
cb50212
refactor: ViewModel 생성 로직 변경
1hyok Nov 13, 2025
179fd7d
refactor: [미션] ViewModel 분리 및 Repository 패턴 적용 시작
1hyok Nov 12, 2025
aca9015
refactor: ViewModel 분리 및 UI 상태 관리 개선
1hyok Nov 13, 2025
fd56889
refactor: ViewModel 팩토리 및 게시글 목록 새로고침 로직 개선
1hyok Nov 13, 2025
460b888
refactor: ViewModel 생성 로직 변경
1hyok Nov 13, 2025
da6b8bb
chore: Gradle 플러그인 버전 업데이트
1hyok Nov 13, 2025
04f83ac
refactor: PostRepository를 인터페이스로 변경 및 PostRepositoryImpl에 모든 메서드 구현
1hyok Nov 13, 2025
4e4cb53
Merge branch 'JeongIlhyuk/week7' of https://github.com/JeongIlhyuk/KU…
1hyok Nov 13, 2025
924862d
docs: ViewModel 수동 주입 관련 주석 추가
1hyok Nov 13, 2025
f817333
refactor: ViewModel 분리 및 Repository 패턴 적용
1hyok Nov 13, 2025
25834c3
refactor: StateFlow 적용 및 UI 상태 관리 개선
1hyok Nov 13, 2025
e64229a
refactor: AppContainer 패키지 경로 변경 및 의존성 주입 구조 개선
1hyok Nov 13, 2025
874812c
docs: PostListScreen에 주석 추가
1hyok Nov 13, 2025
8e1e035
Add configuration for automatic reviews and exclusions
alswlekk Nov 14, 2025
9353238
Merge branch 'Konkuk-KUIT:develop' into JeongIlhyuk/week7
1hyok Nov 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
304 changes: 304 additions & 0 deletions BRANCH_DIFFERENCES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
# practice-only 브랜치와 JeongIlhyuk/week7 브랜치 차이점 정리

## 변경 요약
- **추가된 파일**: 4개
- **수정된 파일**: 10개
- **삭제된 파일**: 1개

---

## 1. 추가된 파일 (A)

### 1.1 `app/src/main/java/com/example/kuit6_android_api/di/AppContainer.kt`
**새로 생성된 파일**
- 의존성 주입을 위한 AppContainer 클래스 추가
- ApiService와 PostRepository를 한 곳에서 관리
- Repository 패턴 구현을 위한 의존성 관리

**주요 내용:**
```kotlin
class AppContainer {
val apiService: ApiService = RetrofitClient.apiService
val postRepository: PostRepository = PostRepositoryImpl(apiService)
}
```

### 1.2 `app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostCreateViewModel.kt`
**새로 생성된 파일**
- PostViewModel을 기능별로 분리한 ViewModel 중 하나
- 게시글 생성 관련 로직 담당
- PostCreateUiState를 통한 상태 관리

**주요 기능:**
- `createPost()`: 게시글 생성
- `uploadImage()`: 이미지 업로드
- `clearUploadedImageUrl()`: 업로드된 이미지 URL 초기화

### 1.3 `app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostDetailViewModel.kt`
**새로 생성된 파일**
- 게시글 상세 조회 및 삭제 관련 ViewModel
- PostDetailUiState를 통한 상태 관리

**주요 기능:**
- `getPostDetail()`: 게시글 상세 조회
- `deletePost()`: 게시글 삭제

### 1.4 `app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostEditViewModel.kt`
**새로 생성된 파일**
- 게시글 수정 관련 ViewModel
- PostEditUiState를 통한 상태 관리

**주요 기능:**
- `getPostDetail()`: 게시글 상세 조회
- `updatePost()`: 게시글 수정
- `uploadImage()`: 이미지 업로드
- `clearUploadedImageUrl()`: 업로드된 이미지 URL 초기화

---

## 2. 삭제된 파일 (D)

### 2.1 `app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModel.kt`
**삭제된 파일**
- 기존의 통합 PostViewModel이 기능별로 분리됨
- PostCreateViewModel, PostDetailViewModel, PostEditViewModel로 분리
- ApiService를 직접 참조하던 구조에서 Repository 패턴으로 변경

---

## 3. 수정된 파일 (M)

### 3.1 `app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepository.kt`

**변경 사항:**
1. **Import 추가:**
- `PostCreateRequest` 추가
- `okhttp3.MultipartBody` 추가

2. **인터페이스 포맷팅:**
- `PostRepository{` → `PostRepository {` (공백 추가)

3. **메서드 추가:**
- `getPostDetail(postId: Long): Result<PostResponse>` - 게시글 상세 조회
- `createPost(author, title, content, imageUrl): Result<PostResponse>` - 게시글 생성
- `updatePost(postId, title, content, imageUrl): Result<PostResponse>` - 게시글 수정
- `deletePost(postId: Long): Result<Unit>` - 게시글 삭제
- `uploadImage(file: MultipartBody.Part): Result<String>` - 이미지 업로드

4. **파일 끝 개행 추가**

### 3.2 `app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepositoryImpl.kt`

**변경 사항:**
1. **Import 추가:**
- `PostCreateRequest` 추가
- `BaseResponse` 추가
- `okhttp3.MultipartBody` 추가

2. **클래스 포맷팅:**
- `PostRepositoryImpl (` → `PostRepositoryImpl(` (공백 제거)
- `): PostRepository {` → `) : PostRepository {` (공백 추가)

3. **getPosts() 메서드 개선:**
- 반환 타입 명시: `BaseResponse<List<PostResponse>>`
- 에러 메시지 변경: "게시긆 불러오기 실패" → "게시글 목록 조회 실패"
- 포맷팅 개선 (공백 추가)

4. **새로운 메서드 구현 추가:**
- `getPostDetail()`: 게시글 상세 조회 구현
- `createPost()`: 게시글 생성 구현
- `updatePost()`: 게시글 수정 구현
- `deletePost()`: 게시글 삭제 구현
- `uploadImage()`: 이미지 업로드 구현

5. **파일 끝 개행 추가**

### 3.3 `app/src/main/java/com/example/kuit6_android_api/ui/navigation/NavGraph.kt`

**변경 사항:**
1. **Import 추가:**
- `PostCreateViewModel` 추가
- `PostDetailViewModel` 추가
- `PostEditViewModel` 추가

2. **PostDetailScreen에서 Factory를 통해 Repository를 ViewModel에 주입:**
```kotlin
viewModel = viewModel(factory = postViewModelFactory { PostDetailViewModel(it) })
```
- Factory가 AppContainer에서 Repository를 가져와 ViewModel 생성자에 전달

3. **PostCreateScreen에서 Factory를 통해 Repository를 ViewModel에 주입:**
```kotlin
viewModel = viewModel(factory = postViewModelFactory { PostCreateViewModel(it) })
```
- Factory가 AppContainer에서 Repository를 가져와 ViewModel 생성자에 전달

4. **PostEditScreen에서 Factory를 통해 Repository를 ViewModel에 주입:**
```kotlin
viewModel = viewModel(factory = postViewModelFactory { PostEditViewModel(it) })
```
- Factory가 AppContainer에서 Repository를 가져와 ViewModel 생성자에 전달

### 3.4 `app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostCreateScreen.kt`

**변경 사항:**
1. **Import 변경:**
- `PostViewModel` → `PostCreateViewModel`
- `postViewModelFactory` 추가

2. **ViewModel 타입 변경:**
- `PostViewModel` → `PostCreateViewModel`
- Factory를 통해 Repository를 ViewModel에 주입

3. **상태 접근 방식 변경:**
- `viewModel.isUploading` → `uiState.isUploading`
- `viewModel.uploadedImageUrl` → `uiState.uploadedImageUrl`
- `val uiState = viewModel.uiState` 추가

4. **주석 추가:**
- Repository 주입 방식에 대한 설명 주석 추가

### 3.5 `app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostDetailScreen.kt`

**변경 사항:**
1. **Import 변경:**
- `PostViewModel` → `PostDetailViewModel`
- `postViewModelFactory` 추가

2. **ViewModel 타입 변경:**
- `PostViewModel` → `PostDetailViewModel`
- Factory를 통해 Repository를 ViewModel에 주입

3. **상태 접근 방식 변경:**
- `viewModel.postDetail` → `uiState.postDetail`
- `val uiState = viewModel.uiState` 추가

4. **LaunchedEffect 주석 해제:**
- `viewModel.getPostDetail(postId)` 호출 활성화

5. **주석 추가:**
- Repository 주입 방식에 대한 설명 주석 추가

### 3.6 `app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostEditScreen.kt`

**변경 사항:**
1. **Import 변경:**
- `PostViewModel` → `PostEditViewModel`
- `postViewModelFactory` 추가

2. **ViewModel 타입 변경:**
- `PostViewModel` → `PostEditViewModel`
- Factory를 통해 Repository를 ViewModel에 주입

3. **상태 접근 방식 변경:**
- `viewModel.postDetail` → `uiState.postDetail`
- `viewModel.uploadedImageUrl` → `uiState.uploadedImageUrl`
- `viewModel.isUploading` → `uiState.isUploading`
- `val uiState = viewModel.uiState` 추가

4. **주석 추가:**
- Repository 주입 방식에 대한 설명 주석 추가

### 3.7 `app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostListScreen.kt`

**변경 사항:**
1. **Import 변경:**
- `PostViewModel` 제거
- `PostListUiState` 제거
- `collectAsState` 제거
- `DisposableEffect`, `LocalLifecycleOwner`, `Lifecycle`, `LifecycleEventObserver` 추가
- `postViewModelFactory` 추가

2. **Factory를 통한 Repository 주입 추가:**
- Factory가 AppContainer에서 Repository를 가져와 ViewModel 생성자에 전달
- 기본값으로 ViewModel 생성

3. **상태 관리 방식 변경:**
- `StateFlow` 기반 → `mutableStateOf` 기반으로 변경
- `collectAsState()` 제거, 직접 `uiState` 접근

4. **Lifecycle 관리 추가:**
- `DisposableEffect`를 사용한 Lifecycle 이벤트 감지
- `ON_RESUME` 이벤트 시 자동 새로고침

5. **UI 구조 단순화:**
- `PostListUiState`의 sealed class 구조 제거
- Loading, Success, Error 상태 분기 제거
- 단순한 LazyColumn으로 변경

6. **LaunchedEffect 추가:**
- 초기 로드 시 `viewModel.refresh()` 호출

### 3.8 `app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostListViewModel.kt`

**변경 사항:**
1. **Import 변경:**
- `PostListUiState` 제거 (파일 내부로 이동)
- `MutableStateFlow`, `StateFlow`, `asStateFlow` 제거
- `mutableStateOf`, `getValue`, `setValue` 추가
- `PostResponse` 추가

2. **상태 관리 방식 변경:**
- `StateFlow` 기반 → `mutableStateOf` 기반으로 변경
- `_uiState`와 `uiState` 분리 구조 제거

3. **PostListUiState 정의 변경:**
- sealed class에서 data class로 변경
- Loading, Success, Error 상태 제거
- 단순히 `posts: List<PostResponse>`만 포함

4. **생성자 파라미터 이름 변경:**
- `postRepository` → `repository`

5. **초기화 로직 변경:**
- `init` 블록 제거
- `loadPosts()` 메서드 제거
- `refresh()` 메서드로 통합

6. **에러 처리 단순화:**
- Error 상태 제거, 실패 시 빈 리스트로 설정

7. **파일 끝 개행 추가**

### 3.9 `app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModelFactory.kt`

**변경 사항:**
1. **주석 추가:**
- Repository 패턴과 수동 주입(App Container)에 대한 설명 주석 추가
- Factory 패턴 사용 목적 설명

### 3.10 `gradle/libs.versions.toml`

**변경 사항:**
1. **AGP 버전 업데이트:**
- `agp = "8.13.0"` → `agp = "8.13.1"`

---

## 주요 아키텍처 변경 사항

### 1. Repository 패턴 도입
- ApiService를 직접 참조하던 구조에서 Repository를 통한 추상화
- 의존성 주입을 통한 테스트 용이성 향상

### 2. ViewModel 분리
- 단일 `PostViewModel`을 기능별로 분리:
- `PostListViewModel`: 목록 조회
- `PostCreateViewModel`: 게시글 생성
- `PostDetailViewModel`: 상세 조회 및 삭제
- `PostEditViewModel`: 게시글 수정

### 3. UiState 구현
- 각 ViewModel에 UiState data class 추가 (PostCreateUiState, PostDetailUiState, PostEditUiState)
- PostListViewModel은 practice-only와 동일하게 StateFlow + sealed class 기반 PostListUiState 유지
- UI 상태를 UiState로 명확히 정의하여 상태 관리 일관성 향상

### 4. 의존성 주입 구조
- `AppContainer`를 통한 중앙 집중식 의존성 관리
- Factory 패턴을 통한 ViewModel 생성 시 Repository 주입
- ViewModel이 Repository를 파라미터로 받아 사용 (의존성 주입)

### 5. Lifecycle 관리 개선
- `LaunchedEffect`를 사용한 초기 로드 시 refresh 함수 실행 (미션 요구사항)
- PostListScreen에서 화면 진입 시 자동으로 데이터 새로고침

69 changes: 69 additions & 0 deletions PROJECT_CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 프로젝트 컨텍스트 및 개발 가이드라인

## 브랜치 구조

### practice-only 브랜치
- **의미**: 미션 반영 전 상태
- **내용**: 강의자가 실습한 코드를 그대로 구현한 것
- **역할**: 기준점(baseline)으로 사용
- **중요**: 이 브랜치의 코드 스타일과 패턴을 크게 벗어나지 않아야 함

### JeongIlhyuk/week7 브랜치
- **의미**: 미션 반영 후 상태
- **내용**: 미션 요구사항을 반영한 코드
- **역할**: 미션 완료 버전

---

## 미션 요구사항 (체크리스트)

- [x] 수동 주입(App Container) 구현
- [x] Repository 패턴 사용
- [x] ViewModel 분리
- PostEditViewModel
- PostDetailViewModel (삭제까지 같이 하시면 됩니다)
- PostCreateViewModel
- [x] UiState 구현
- [x] PostViewModel 삭제
- [x] PostListViewModel의 refresh 함수를 메인화면에서 sideEffect로 항상 실행시키기

---

## 개발 원칙

### ⚠️ 중요 사항
1. **미션 요구사항에 벗어나는 불필요한 변경 금지**
- 미션에서 요구하지 않은 변경사항은 만들지 않기
- 예: StateFlow → mutableStateOf 변경은 미션 요구사항이 아님 (단순히 선택된 방식)

2. **practice-only 브랜치의 코드 스타일 유지**
- 강의자가 실습한 코드의 패턴과 스타일을 존중
- 불필요한 리팩토링이나 스타일 변경 지양

3. **변경사항 검증**
- 모든 변경사항이 미션 요구사항과 직접적으로 연관되어 있는지 확인
- practice-only 브랜치와 비교하여 불필요한 차이점이 없는지 확인

---

## 브랜치 비교 시 주의사항

### 비교 방법
```bash
# practice-only (미션 전) vs JeongIlhyuk/week7 (미션 후)
git diff practice-only JeongIlhyuk/week7
```

### 확인해야 할 사항
1. 변경사항이 미션 요구사항과 직접 연관이 있는가?
2. practice-only의 코드 스타일을 크게 벗어나지 않는가?
3. 불필요한 리팩토링이나 개선이 포함되어 있지 않은가?

---

## 참고사항

- practice-only 브랜치는 강의자의 실습 코드이므로, 이를 기준으로 미션만 반영해야 함
- 미션 요구사항 외의 "개선"이나 "최적화"는 지양
- 코드 스타일, 네이밍, 구조는 practice-only 브랜치를 따르는 것을 원칙으로 함

1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
android:maxSdkVersion="32" />

<application
android:name=".App"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/example/kuit6_android_api/App.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.kuit6_android_api

import android.app.Application
import com.example.kuit6_android_api.data.di.AppContainer

class App: Application() {
lateinit var container: AppContainer

override fun onCreate(){
super.onCreate()
container = AppContainer()
}
}
Loading