-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 마이 페이지 API (FITRUN-72) #77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
The head ref may contain hidden characters: "FITRUN-72-Server-\uB9C8\uC774-\uD398\uC774\uC9C0-API"
Conversation
""" Walkthrough이번 변경에서는 약관(Term) 관련 도메인, 서비스, 컨트롤러, 변환기, 테스트 및 픽스처가 신규로 도입되었습니다. 또한 사용자(User) 관련 응답 객체와 서비스에 러너 타입(runnerType) 및 목표(goal) 정보를 포함하도록 확장하고, 이에 따른 API, 테스트, 문서가 일괄적으로 개선되었습니다. 일부 기존 코드의 생성자 및 반환 객체 생성 방식도 간소화되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant TermController
participant TermService
participant TermManager
participant TermDao
participant TermRepository
Client->>TermController: GET /api/v1/terms/{termType}
TermController->>TermService: getTermByTermType(termType)
TermService->>TermManager: getTermByTermType(termType)
TermManager->>TermDao: getTermByTermType(termType)
TermDao->>TermRepository: findByTermType(termType)
TermRepository-->>TermDao: Term?
TermDao-->>TermManager: Term
TermManager-->>TermService: Term
TermService-->>TermController: TermResponse
TermController-->>Client: ApiResponse<TermResponse>
sequenceDiagram
participant Client
participant UserController
participant UserService
participant UserGoalManager
Client->>UserController: GET /api/v1/users
UserController->>UserService: getUserAndGoalById(id)
UserService->>UserGoalManager: findUserGoal(user)
UserGoalManager-->>UserService: UserGoal?
UserService-->>UserController: UserAndGoalResponse
UserController-->>Client: ApiResponse<UserAndGoalResponse>
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (4)
🧰 Additional context used🧠 Learnings (2)📓 Common learnings
📚 Learning: xml 응답을 테스트하는 spring rest docs에서는 응답 필드 문서화(`restdocsresponse`)를 추가하면 테스트가 실패할 수 있다. xml api 테스트에서는 ...
Applied to files:
🧬 Code Graph Analysis (1)src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt (2)
🔇 Additional comments (6)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
기타 참고 사항 확인 부탁드립니다!! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
src/main/kotlin/com/yapp/yapp/common/web/config/WebConfig.kt (1)
21-23
: Converter 등록 방식 개선 제안
Bean 으로 이미 등록된ProviderTypeConverter
를 새로 생성하여 등록하면 설정 중복·테스트 어려움이 생깁니다. 생성 대신 의존성 주입으로 처리하거나,@Component
만으로 자동 등록되므로 아래 줄 자체를 제거할 수 있습니다.- override fun addFormatters(registry: FormatterRegistry) { - registry.addConverter(ProviderTypeConverter()) - } + // Converter Bean 은 ComponentScan 으로 자동 등록되므로 별도 추가 불필요 + override fun addFormatters(registry: FormatterRegistry) { + // 필요 시 다른 Formatter 만 추가 + }또한 이번 PR 에서 추가된
TermTypeConverter
도 같은 방식으로 자동 등록되므로 수동 등록 코드가 없어도 됩니다.
🧹 Nitpick comments (7)
src/test/kotlin/com/yapp/yapp/user/UserControllerTest.kt (1)
54-54
: 이메일 변수 사용 일관성 개선 제안Line 54에서
getAccessToken(user.email)
을 사용하고 있지만, Line 52에서 정의한getAccessToken(email)
을 사용하는 것을 고려해보세요.- val accessToken = getAccessToken(user.email) + val accessToken = getAccessToken(email)src/main/kotlin/com/yapp/yapp/common/web/converter/ProviderTypeConverter.kt (1)
7-10
: 불필요한 수동 인스턴스화
@Component
가 붙어 있어 Spring Bean 으로 자동 등록됩니다. 다른 곳(WebConfig 등)에서ProviderTypeConverter()
를 직접 생성하지 말고 DI 로 주입하거나, 아예addFormatters
호출을 제거해도 됩니다.src/test/kotlin/com/yapp/yapp/support/BaseSupportMethod.kt (1)
22-24
: Fixture 사용 시 초기화 순서 유의
lateinit var termFixture
로 선언했으므로, 테스트 메서드 실행 전에 Spring 컨텍스트가 정상적으로 Fixture 를 주입하지 못하면UninitializedPropertyAccessException
이 발생할 수 있습니다. 필드 주입 대신 생성자 주입으로 변경하면 안전성을 높일 수 있습니다.src/main/kotlin/com/yapp/yapp/term/domain/TermManager.kt (1)
5-10
: 불필요한 중간 계층일 수 있습니다.현재 구현에서는 TermDao로의 단순 위임만 수행하고 있어 추가적인 비즈니스 로직이 없다면 불필요한 계층일 수 있습니다. TermService에서 직접 TermDao를 사용하는 것을 고려해보세요.
만약 향후 복잡한 비즈니스 로직 추가 계획이 있다면 현재 구조를 유지하는 것이 좋습니다.
src/main/kotlin/com/yapp/yapp/term/domain/TermService.kt (1)
6-14
: 적절한 서비스 계층 구현입니다.도메인 엔티티를 응답 DTO로 변환하는 책임을 명확히 분리했습니다. 다만 TermManager가 단순 위임만 하고 있다면, 직접 TermDao를 의존성으로 주입받아 사용하는 것을 고려해보세요.
src/main/kotlin/com/yapp/yapp/term/domain/TermType.kt (1)
6-11
: enum 클래스 선언에서 불필요한 구문 요소가 있습니다.enum 클래스의 빈 괄호와 마지막 세미콜론은 Kotlin에서 불필요합니다.
다음과 같이 정리할 수 있습니다:
-enum class TermType() { +enum class TermType { SERVICE, PRIVATE_POLICY, LOCATION, - WITHDRAW, - ; + WITHDRAWsrc/test/kotlin/com/yapp/yapp/support/fixture/TermFixture.kt (1)
15-28
: 콘텐츠 필드의 기본값을 개선하는 것을 고려해보세요.현재 반복적인 플레이스홀더 텍스트와 생략 부호(...)는 테스트 시나리오에서 혼란을 줄 수 있습니다. 보다 의미 있는 약관 내용으로 개선하면 테스트 품질이 향상될 것입니다.
예시로 다음과 같이 개선할 수 있습니다:
- content: String = - """ - 개인정보처리방침 정책 - ... - ... - ... - 개인정보처리방침 정책 - 개인정보처리방침 정책 - 개인정보처리방침 정책 - 개인정보처리방침 정책 - 개인정보처리방침 정책 - 개인정보처리방침 정책 - ... - """.trimIndent(), + content: String = + """ + 제1조 (개인정보의 처리목적) + 당사는 다음의 목적을 위하여 개인정보를 처리합니다. + + 1. 회원가입 및 관리 + 2. 서비스 제공 + 3. 고객 문의 응답 + + 제2조 (개인정보의 처리 및 보유기간) + 개인정보는 법정 보유기간 또는 정보주체로부터 개인정보를 수집시에 동의받은 개인정보 보유기간 내에서 처리 및 보유합니다. + """.trimIndent(),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (28)
src/main/kotlin/com/yapp/yapp/auth/domain/AuthService.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/common/exception/ErrorCode.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/common/web/config/WebConfig.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/common/web/converter/ProviderTypeConverter.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/common/web/converter/TermTypeConverter.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/api/TermController.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/api/response/TermResponse.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/domain/Term.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/domain/TermDao.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/domain/TermManager.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/domain/TermRepository.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/domain/TermService.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/term/domain/TermType.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/user/api/UserController.kt
(2 hunks)src/main/kotlin/com/yapp/yapp/user/api/response/UserAndGoalResponse.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/user/api/response/UserResponse.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/user/domain/UserInfo.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/user/domain/UserManager.kt
(1 hunks)src/main/kotlin/com/yapp/yapp/user/domain/UserService.kt
(3 hunks)src/main/kotlin/com/yapp/yapp/user/domain/goal/UserGoalManager.kt
(1 hunks)src/test/kotlin/com/yapp/yapp/auth/api/controller/AuthControllerTest.kt
(6 hunks)src/test/kotlin/com/yapp/yapp/document/Tag.kt
(1 hunks)src/test/kotlin/com/yapp/yapp/document/auth/AuthDocumentTest.kt
(1 hunks)src/test/kotlin/com/yapp/yapp/document/term/TermDocumentTest.kt
(1 hunks)src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt
(3 hunks)src/test/kotlin/com/yapp/yapp/support/BaseSupportMethod.kt
(2 hunks)src/test/kotlin/com/yapp/yapp/support/fixture/TermFixture.kt
(1 hunks)src/test/kotlin/com/yapp/yapp/user/UserControllerTest.kt
(2 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: jhon3242
PR: YAPP-Github/26th-App-Team-4-BE#44
File: src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt:0-0
Timestamp: 2025-07-11T02:24:46.949Z
Learning: YAPP-Github/26th-App-Team-4-BE 프로젝트에서는 API 문서 테스트(Spring REST Docs)의 목적을 문서화에 집중하고, 세부 로직에 대한 테스트는 진행하지 않는 것으로 통일한다. 이는 테스트의 관심사 분리를 위한 아키텍처 결정이다.
src/test/kotlin/com/yapp/yapp/document/auth/AuthDocumentTest.kt (1)
Learnt from: jhon3242
PR: #44
File: src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt:0-0
Timestamp: 2025-07-11T02:24:46.949Z
Learning: YAPP-Github/26th-App-Team-4-BE 프로젝트에서는 API 문서 테스트(Spring REST Docs)의 목적을 문서화에 집중하고, 세부 로직에 대한 테스트는 진행하지 않는 것으로 통일한다. 이는 테스트의 관심사 분리를 위한 아키텍처 결정이다.
src/main/kotlin/com/yapp/yapp/user/domain/goal/UserGoalManager.kt (1)
Learnt from: jhon3242
PR: #43
File: src/main/kotlin/com/yapp/yapp/user/domain/goal/UserGoalRepository.kt:6-8
Timestamp: 2025-07-10T14:16:05.498Z
Learning: UserGoal과 User 간의 관계는 1:1이고 단방향입니다 (UserGoal -> User). 이는 UserGoal이 User에 대한 외래키를 가지지만, User는 UserGoal을 직접 참조하지 않음을 의미합니다.
src/main/kotlin/com/yapp/yapp/user/api/response/UserAndGoalResponse.kt (1)
Learnt from: jhon3242
PR: #43
File: src/main/kotlin/com/yapp/yapp/user/domain/goal/UserGoalRepository.kt:6-8
Timestamp: 2025-07-10T14:16:05.498Z
Learning: UserGoal과 User 간의 관계는 1:1이고 단방향입니다 (UserGoal -> User). 이는 UserGoal이 User에 대한 외래키를 가지지만, User는 UserGoal을 직접 참조하지 않음을 의미합니다.
src/test/kotlin/com/yapp/yapp/document/term/TermDocumentTest.kt (2)
Learnt from: jhon3242
PR: #44
File: src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt:0-0
Timestamp: 2025-07-11T02:24:46.949Z
Learning: YAPP-Github/26th-App-Team-4-BE 프로젝트에서는 API 문서 테스트(Spring REST Docs)의 목적을 문서화에 집중하고, 세부 로직에 대한 테스트는 진행하지 않는 것으로 통일한다. 이는 테스트의 관심사 분리를 위한 아키텍처 결정이다.
Learnt from: jhon3242
PR: #32
File: src/test/kotlin/com/yapp/yapp/document/running/RunningDocumentTest.kt:130-167
Timestamp: 2025-07-02T06:05:46.573Z
Learning: XML 응답을 테스트하는 Spring REST Docs에서는 응답 필드 문서화(restDocsResponse
)를 추가하면 테스트가 실패할 수 있다. XML API 테스트에서는 응답 필드 문서화를 제외하더라도 API 문서에 예시 값이 정상적으로 표시된다.
src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt (1)
Learnt from: jhon3242
PR: #32
File: src/test/kotlin/com/yapp/yapp/document/running/RunningDocumentTest.kt:130-167
Timestamp: 2025-07-02T06:05:46.573Z
Learning: XML 응답을 테스트하는 Spring REST Docs에서는 응답 필드 문서화(restDocsResponse
)를 추가하면 테스트가 실패할 수 있다. XML API 테스트에서는 응답 필드 문서화를 제외하더라도 API 문서에 예시 값이 정상적으로 표시된다.
src/test/kotlin/com/yapp/yapp/user/UserControllerTest.kt (1)
Learnt from: jhon3242
PR: #44
File: src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt:0-0
Timestamp: 2025-07-11T02:24:46.949Z
Learning: YAPP-Github/26th-App-Team-4-BE 프로젝트에서는 API 문서 테스트(Spring REST Docs)의 목적을 문서화에 집중하고, 세부 로직에 대한 테스트는 진행하지 않는 것으로 통일한다. 이는 테스트의 관심사 분리를 위한 아키텍처 결정이다.
🧬 Code Graph Analysis (3)
src/test/kotlin/com/yapp/yapp/document/term/TermDocumentTest.kt (1)
src/test/kotlin/com/yapp/yapp/document/support/BaseDocumentTest.kt (1)
filter
(76-79)
src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt (2)
src/test/kotlin/com/yapp/yapp/document/support/BaseDocumentTest.kt (1)
getAccessToken
(81-84)src/test/kotlin/com/yapp/yapp/support/BaseControllerTest.kt (1)
getAccessToken
(57-60)
src/test/kotlin/com/yapp/yapp/user/UserControllerTest.kt (1)
src/test/kotlin/com/yapp/yapp/support/BaseControllerTest.kt (1)
getAccessToken
(57-60)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Run tests and generate API docs
🔇 Additional comments (34)
src/test/kotlin/com/yapp/yapp/document/auth/AuthDocumentTest.kt (1)
46-46
: 문서화 추가가 적절합니다.새로 추가된
runnerType
필드에 대한 문서화가 올바르게 추가되었습니다. 설명도 명확하고 다른 필드들과 일관성을 유지하고 있습니다.src/main/kotlin/com/yapp/yapp/auth/domain/AuthService.kt (1)
40-40
: 생성자 호출 방식 개선이 좋습니다.개별 필드를 전달하는 대신
userInfo
객체 전체를 전달하는 방식으로 변경하여 코드가 더 간결해지고 유지보수성이 향상되었습니다. 새로운 필드가 추가될 때 누락될 위험도 줄어들었습니다.src/main/kotlin/com/yapp/yapp/user/api/response/UserAndGoalResponse.kt (1)
3-6
: 새로운 응답 클래스가 적절합니다.사용자 정보와 목표 정보를 함께 반환하기 위한 간단하고 명확한 구조입니다.
goal
을 nullable로 설정한 것도 모든 사용자가 목표를 설정하지 않을 수 있다는 점을 고려할 때 적절합니다.src/main/kotlin/com/yapp/yapp/user/domain/goal/UserGoalManager.kt (1)
74-76
: 선택적 목표 조회 메서드 추가가 유용합니다.기존의
getUserGoal
과 달리 null을 반환할 수 있는findUserGoal
메서드를 추가하여, 목표가 설정되지 않은 사용자에 대해서도 안전하게 처리할 수 있게 되었습니다.UserAndGoalResponse
의 nullable goal 필드와 잘 맞는 설계입니다.src/main/kotlin/com/yapp/yapp/user/domain/UserManager.kt (1)
16-23
: UserInfo 생성 방식 개선이 훌륭합니다.저장된
user
객체에서 직접 값을 가져와UserInfo
를 생성하는 방식으로 변경하여 데이터 일관성이 향상되었습니다. 특히user.provider
를 사용하고runnerType
을 포함하여 완전한 사용자 정보를 제공하며,isNew=true
를 명시적으로 설정하여 의도를 명확히 했습니다.src/main/kotlin/com/yapp/yapp/user/domain/UserInfo.kt (1)
10-10
: LGTM! runnerType 필드 추가가 적절합니다.nullable
RunnerType?
타입 사용과 생성자에서의 매핑이 올바르게 구현되었습니다. 온보딩을 완료하지 않은 사용자의 경우를 고려한 nullable 처리가 적절합니다.Also applies to: 18-18
src/test/kotlin/com/yapp/yapp/auth/api/controller/AuthControllerTest.kt (1)
66-66
: 테스트 케이스 업데이트가 일관성 있게 잘 구현되었습니다.신규 사용자의 경우 온보딩을 완료하지 않았으므로
runnerType
이null
인 것을 검증하는 것이 적절합니다. 모든 로그인 시나리오에서 일관되게 적용되었습니다.Also applies to: 105-105, 146-146, 187-187, 310-310, 366-366
src/main/kotlin/com/yapp/yapp/user/api/UserController.kt (1)
8-8
: API 응답 구조 변경이 올바르게 구현되었습니다.
UserAndGoalResponse
로 변경하여 사용자 정보와 목표 정보를 함께 제공하는 것이 마이페이지 API의 요구사항에 적합합니다.이 변경은 기존 API 응답 구조를 변경하는 breaking change입니다. 클라이언트 팀과 API 스펙 변경에 대해 충분히 협의했는지 확인해 주세요.
Also applies to: 28-29
src/main/kotlin/com/yapp/yapp/user/domain/UserService.kt (2)
76-83
: 새로운getUserAndGoalById
메서드가 잘 구현되었습니다.읽기 전용 트랜잭션 설정, optional한 목표 정보 처리, 그리고 응답 객체 생성 로직이 적절합니다. 기존 패턴을 따라 일관성 있게 구현되었습니다.
93-93
: 기존getUserById
메서드의runnerType
필드 추가가 적절합니다.기존 메서드의 호환성을 유지하면서 새로운 필드를 추가한 것이 좋습니다.
src/test/kotlin/com/yapp/yapp/document/user/UserDocumentTest.kt (2)
29-48
: API 문서화가 새로운 응답 구조에 맞게 잘 업데이트되었습니다.중첩된
result.user
구조와 optional한goal
객체에 대한 필드 명세가 정확하게 작성되었습니다.JsonFieldType
과optional()
설정이 적절히 적용되었습니다.
59-61
: 테스트 설정 개선이 훌륭합니다.사용자와 목표 정보를 모두 생성하여 완전한 API 응답 예시를 문서화할 수 있도록 한 것이 좋습니다. 이는 API 문서의 품질을 향상시킵니다.
src/main/kotlin/com/yapp/yapp/user/api/response/UserResponse.kt (4)
4-6
: 새로운 import 추가가 적절합니다RunnerType, User, UserInfo 클래스를 import하여 새로운 기능을 지원하는 것이 올바릅니다.
13-13
: runnerType을 nullable로 설정한 것이 적절합니다러너 타입이 항상 설정되지 않을 수 있으므로 nullable로 선언한 것이 합리적입니다.
15-21
: User 도메인 객체를 위한 편의 생성자가 잘 구현되었습니다모든 필드를 적절히 매핑하고 있으며, 새로 추가된 runnerType도 올바르게 포함되어 있습니다.
23-29
: UserInfo 도메인 객체를 위한 편의 생성자가 잘 구현되었습니다User 생성자와 일관된 매핑 방식을 사용하고 있어 코드의 일관성이 유지됩니다.
src/test/kotlin/com/yapp/yapp/user/UserControllerTest.kt (4)
5-5
: UserAndGoalResponse로 import 변경이 적절합니다API 응답 구조 변경에 맞춰 import를 올바르게 업데이트했습니다.
13-18
: 목표가 있는 사용자 테스트 설정이 적절합니다사용자와 목표를 모두 생성하여 완전한 테스트 시나리오를 구성했습니다.
31-46
: UserAndGoalResponse에 대한 포괄적인 검증이 잘 구현되었습니다사용자 정보와 목표 정보를 모두 검증하고 있으며, 새로 추가된 runnerType 필드도 적절히 확인하고 있습니다.
49-77
: 목표가 없는 사용자 테스트가 잘 추가되었습니다목표가 없는 경우에 대한 시나리오를 별도로 테스트하여 테스트 커버리지가 향상되었습니다. goal 필드가 null인지 확인하는 것이 적절합니다.
src/test/kotlin/com/yapp/yapp/document/Tag.kt (1)
15-16
:TERM_API
태그 추가 확인 완료
표기 규칙 및 enum 구조와도 일관성이 있습니다. 별다른 문제 없습니다.src/main/kotlin/com/yapp/yapp/common/web/converter/ProviderTypeConverter.kt (1)
1-1
: 구 패키지 참조 없음 확인 완료
com.yapp.yapp.auth.infrastructure.provider.ProviderTypeConverter
를 참조하는 import가 더 이상 존재하지 않습니다. 모든 곳에서 변경된 경로(com.yapp.yapp.common.web.converter.ProviderTypeConverter
)만 사용되고 있어 컴파일 오류가 발생하지 않습니다.src/main/kotlin/com/yapp/yapp/common/web/config/WebConfig.kt (1)
8-9
: 패키지 경로 수정 적절
import 경로가 새 위치로 정상 수정되었습니다.src/test/kotlin/com/yapp/yapp/support/BaseSupportMethod.kt (1)
7-9
:TermFixture
주입 추가 확인
테스트 기반 데이터 생성을 위해 Fixture 를 확장한 점 확인했습니다. 다른 테스트 클래스에서도 동일한 Fixture 주입을 기대하므로,@Component
스캔 범위와 패키지 위치가 일치하는지 한번 더 확인해주세요.src/main/kotlin/com/yapp/yapp/term/domain/TermRepository.kt (1)
5-7
: 적절한 JPA 리포지토리 구현입니다.Spring Data JPA 규칙을 잘 따르고 있으며, nullable 반환 타입으로 존재하지 않는 약관 타입에 대한 처리를 고려한 설계입니다.
src/main/kotlin/com/yapp/yapp/common/web/converter/TermTypeConverter.kt (1)
7-10
: 깔끔한 컨버터 구현입니다.Spring의 Converter 인터페이스를 올바르게 구현하고 있으며, TermType.from() 메서드로의 위임이 적절합니다. TermType.from()에서 잘못된 입력에 대한 예외 처리가 적절히 구현되어 있는지 확인해 주세요.
src/main/kotlin/com/yapp/yapp/term/api/response/TermResponse.kt (1)
5-15
: 잘 설계된 응답 DTO입니다.도메인 객체를 받는 보조 생성자를 통해 깔끔한 변환을 제공하고 있으며, 필요한 모든 필드가 적절히 포함되어 있습니다. 데이터 클래스 사용도 적절합니다.
src/main/kotlin/com/yapp/yapp/term/domain/TermDao.kt (1)
7-14
: DAO 구현이 깔끔하게 되어있습니다.데이터 접근 로직의 캡슐화가 잘 되어있고, null 체크 후 적절한 예외 처리도 구현되어 있습니다. 메서드명을
getByTermType
으로 더 간결하게 할 수도 있겠지만, 현재도 충분히 명확합니다.src/main/kotlin/com/yapp/yapp/term/domain/TermType.kt (1)
13-18
: 문자열 변환 로직이 잘 구현되어 있습니다.대소문자를 구분하지 않는 변환 로직과 적절한 예외 처리가 구현되어 있어 사용자 친화적입니다.
src/main/kotlin/com/yapp/yapp/term/domain/Term.kt (1)
14-30
: JPA 엔티티 설계가 잘 되어있습니다.테이블 매핑, 필드 타입 선택(특히 content에 @lob 사용), enum 저장 방식(STRING) 모두 적절합니다. BaseTimeEntity 상속으로 생성/수정 시간 관리도 일관성 있게 처리되고 있습니다.
src/main/kotlin/com/yapp/yapp/term/api/TermController.kt (1)
12-25
: REST 컨트롤러 구현이 프로젝트 규칙을 잘 따르고 있습니다.URL 구조가 RESTful하고, ApiResponse 래퍼 사용으로 일관된 응답 형식을 유지하고 있습니다. PathVariable로 TermType enum을 직접 바인딩하는 것도 깔끔합니다.
src/test/kotlin/com/yapp/yapp/document/term/TermDocumentTest.kt (1)
10-46
: API 문서화 테스트가 프로젝트 규칙에 맞게 잘 구현되어 있습니다.프로젝트의 아키텍처 결정에 따라 문서화에 집중하고 있으며, REST Docs를 활용한 필드 문서화와 한글 설명이 적절합니다. termFixture 사용으로 테스트 데이터 생성도 깔끔하게 처리되고 있습니다.
src/test/kotlin/com/yapp/yapp/support/fixture/TermFixture.kt (2)
8-11
: Spring 컴포넌트 구조가 적절합니다.
@Component
어노테이션과 생성자 주입을 통한 의존성 관리가 올바르게 구현되었습니다. 테스트 픽스처가 Spring 컨텍스트에서 재사용 가능하도록 잘 설계되었습니다.
12-39
: 픽스처 메서드 구현이 적절합니다.기본값 제공과 커스터마이징 가능한 매개변수 구조가 잘 설계되었습니다.
TermType.PRIVATE_POLICY
와isRequired = true
는 합리적인 기본값입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
재용님 수고하셨습니다!!
의견 남겼는데 확인 부탁드려요!
회사 다니면서 작업하는 재용님 리스팩합니다!! ㅋㅋㅋ
약관에 대한 생성, 업데이트 API 작업하지 않았습니다(관리자 구분 필요)
이 부분은 지금 단계에서는 필요 없을 것 같긴하네요! 만약 어드민 페이지가 생긴다면 그때 고려하면 될 것 같습니다!
사용자 약관 동의 테이블(UserTerm)도 현재 별도로 작업하지 않았습니다. (약관 동의 시점 불분명)
사용자가 저희 서비스를 이용하려면 모든 약관의 동의했다는 것이 전제가 되면 상관 없을 것 같아요.
그런데 만약 미동의 상태로 저희 서비스를 이용할 수 있다면, 사용자마다 어떤 약관의 동의했는지를 저장해야해서 UserTerm이 필요할 것 같습니다. 이 부분은 기획에 따라서 구현할지말지 방향성을 정하면 좋을 것 같아요!
userInfo.email, | ||
userInfo.provider, | ||
) | ||
val userResponse = UserResponse(userInfo) | ||
return LoginResponse(tokenResponse, userResponse, userInfo.isNew) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사소한 의견)
👍 넘 깔끔해졌네요!
근데 LoginResponse 에서 도메인을 받아서 내부에서 userResponse와 tokenResponse를 생성하는 형식은 어떠신가요??
userResponse와 tokenResponse는 내부 응답 객체를 위한 것인데 Service에서 생성해주는게 맞을까 의문이 들어서요!
아래와 같이요!
data class LoginResponse(
val tokenResponse: TokenResponse,
val user: UserResponse,
val isNew: Boolean = false,
) {
constructor(tokenInfo: TokenInfo, userInfo: UserInfo):
this(
tokenResponse = TokenResponse(
accessToken = tokenInfo.accessToken,
refreshToken = tokenInfo.refreshToken,
),
user = UserResponse(userInfo),
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋은 것 같습니다!!
companion object { | ||
fun from(name: String): TermType = | ||
entries.firstOrNull { it.name.equals(name, ignoreCase = true) } | ||
?: throw CustomException(ErrorCode.INVALID_REQUEST) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
의견)
Resource Not Found 인지, No Matched Type 인지 구분되었으면 좋을 것 같아요.
실제로 에러 발생시 INVALID_REQUEST만 보았을 때 문제의 원인을 파악하기 어렵더라고요.
물론 서버의 정보를 노출하는 것은 지양해야하지만, 어떤 형태의 문제인지 정도는 구분해주면 좋을 것 같습니다! 예를 들어서 URI가 잘못된 것인지, 헤더가 잘못된 것인지, 파라미터가 잘못된 것인지 , 필드가 잘못된 것인지 등으로요!
이미 구현한 코드들이 있어서 이 부분은 따로 PR 파서 작업하는 것도 좋을 것 같네용.. 작업 리소스가 좀 소모되는 만큼 재용님의 의견을 듣고 싶네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
에러 로그 보고 파악이 어려운건 공감하는 부분입니다. 이 부분도 반영하겠습니다~~
@Transactional(readOnly = true) | ||
fun getUserAndGoalById(id: Long): UserAndGoalResponse { | ||
val user = userManager.getActiveUser(id) | ||
val userResponse = UserResponse(user) | ||
val userGoal = userGoalManager.findUserGoal(user) | ||
val userGoalResponse = userGoal?.let { UserGoalResponse(it) } | ||
return UserAndGoalResponse(user = userResponse, goal = userGoalResponse) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사소한 의견)
어떤 id인지도 메서드명에 들어나면 좋을 것 같네요! 아니면 필드에서 userId라고 해주는 것도 좋을 것 같고요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사소한 의견)
UserAndGoalResponse(user = userResponse, goal = userGoalResponse)
이 부분도 앞선 리뷰와 동일하게 DTO 생성자에서 엔티티를 받아 처리해주면 어떨까요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 둘 다 반영하겠습니다.
@@ -80,6 +90,7 @@ class UserService( | |||
nickname = user.nickname, | |||
email = user.email, | |||
provider = user.provider, | |||
runnerType = user.runnerType, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사소한 의견)
제가 이전에 만들어 뒀었는데 해당 메서드는 사용하지 않는 것 같네용 삭제해주시면 좋을 것 같습니다!
@@ -101,6 +102,7 @@ class AuthControllerTest : BaseControllerTest() { | |||
{ Assertions.assertThat(response.user.userId).isNotNull() }, | |||
{ Assertions.assertThat(response.user.email).isNotNull() }, | |||
{ Assertions.assertThat(response.user.nickname).isNotNull() }, | |||
{ Assertions.assertThat(response.user.runnerType).isNull() }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 👍
val restDocsRequest = | ||
request() | ||
.pathParameter( | ||
parameterWithName("termType").description("약관 타입 (service, private_policy, location, withdraw) 중 하나 - case insensitive"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case insensitive라는게 대소문자 구분 없다는 말이군요! 배워갑니다 ㅋㅋㅋㅋ
) | ||
|
||
val filter = | ||
filter("term", "term-search") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 이 부분도 빼먹지 않고 영어로 해주셨네요!! 크으 👍
fieldWithPath("result.user.userId").description("사용자 ID"), | ||
fieldWithPath("result.user.email").description("사용자 이메일"), | ||
fieldWithPath("result.user.nickname").description("사용자 닉네임"), | ||
fieldWithPath("result.user.provider").description("소셜 로그인 유형"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
의견)
어떤 유형이 있는지도 설명해주면 좋을 것 같습니다! (kakao, apple)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵!! 이전에 해둔거라 지나쳤네요
fieldWithPath("result.user.email").description("사용자 이메일"), | ||
fieldWithPath("result.user.nickname").description("사용자 닉네임"), | ||
fieldWithPath("result.user.provider").description("소셜 로그인 유형"), | ||
fieldWithPath("result.user.runnerType").description("사용자 러너 유형").type(JsonFieldType.STRING).optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사소한 의견)
여기도 마찬가지로요!
"대회 준비: COMPETITION_PREPARATION", | ||
).type(JsonFieldType.STRING).optional(), | ||
fieldWithPath("result.goal.weeklyRunningCount").description("주간 달리기 횟수").type(JsonFieldType.NUMBER).optional(), | ||
fieldWithPath("result.goal.paceGoal").description("페이스 목표 시간 밀리초 단위").type(JsonFieldType.NUMBER).optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
단위 설명까지 굿굿 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
원준님꺼 복붙..🙂🙂
UserTerm은 기능상 중요한 부분도 아니고 다른 분들이 현재 신경 쓸게 많은거 같아 시간 여유 있을 때 말해보고 적용하겠습니다!! |
📎 관련 이슈
📄 추가 작업 내용
✅ Check List
💬 기타 참고 사항
약관에 대한 생성, 업데이트 API 작업하지 않았습니다(관리자 구분 필요)
사용자 약관 동의 테이블(UserTerm)도 현재 별도로 작업하지 않았습니다. (약관 동의 시점 불분명)
위 참고 사항에 대해 어떻게 생각하시나요? 구현이 추가로 필요하다면 별도의 PR로 작업하겠습니다!!
Summary by CodeRabbit
Summary by CodeRabbit
신규 기능
기능 개선
버그 수정
문서화 및 테스트