Conversation
|
""" Walkthrough이 PR은 Alias와 Tag 도메인을 enum 기반으로 리팩토링하고, 기존의 ID 기반 식별 방식을 이름 기반 문자열 식별로 대체합니다. 이에 따라 관련 매퍼, 포트, 서비스, 엔티티, DTO, 테스트 코드 전반에 걸쳐 필드 타입 및 매핑 로직이 변경되었으며, 불필요해진 매퍼 및 포트 클래스가 삭제되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant UserSignupController
participant UserSignupService
participant Alias(enum)
participant User
participant UserCommandPersistenceAdapter
participant AliasJpaRepository
Client->>UserSignupController: 회원가입 요청(aliasName, nickname)
UserSignupController->>UserSignupService: signup(command)
UserSignupService->>Alias: Alias.from(aliasName)
Alias-->>UserSignupService: Alias enum 반환 or 예외
UserSignupService->>User: User.withoutId(..., alias)
UserSignupService->>UserCommandPersistenceAdapter: save(user)
UserCommandPersistenceAdapter->>AliasJpaRepository: findByValue(user.alias.value)
AliasJpaRepository-->>UserCommandPersistenceAdapter: Optional<AliasJpaEntity>
UserCommandPersistenceAdapter-->>UserSignupService: 저장 결과 반환
UserSignupService-->>UserSignupController: 결과 반환
UserSignupController-->>Client: 응답
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
🪧 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.
Actionable comments posted: 5
🧹 Nitpick comments (3)
src/main/java/konkuk/thip/user/domain/AliasName.java (1)
21-28: from() 메서드 성능 개선 제안현재 구현은 매번 전체 배열을 순회하고 있습니다. 성능을 개선하기 위해 static Map을 사용하는 것을 고려해보세요.
다음과 같이 개선할 수 있습니다:
+import java.util.Map; +import java.util.stream.Collectors; +import java.util.Arrays; + +@Getter +public enum AliasName { + // ... enum constants + + private static final Map<String, AliasName> VALUE_MAP = + Arrays.stream(values()) + .collect(Collectors.toMap(AliasName::getValue, alias -> alias)); + public static AliasName from(String aliasName) { - for (AliasName name : AliasName.values()) { - if (name.value.equals(aliasName)) { - return name; - } - } - throw new InvalidStateException(ErrorCode.ALIAS_NAME_NOT_MATCH); + AliasName result = VALUE_MAP.get(aliasName); + if (result == null) { + throw new InvalidStateException(ErrorCode.ALIAS_NAME_NOT_MATCH); + } + return result; }src/main/java/konkuk/thip/feed/domain/TagName.java (1)
32-40: case-insensitive 검색 로직의 성능 개선을 고려해보세요.현재 구현은 선형 검색을 수행하며, 매번 호출시마다 모든 enum 값을 순회합니다. 더 효율적인 방법을 고려해볼 수 있습니다.
+ private static final Map<String, TagName> TAG_MAP = Arrays.stream(TagName.values()) + .collect(Collectors.toMap( + tagName -> tagName.tag.toLowerCase(), + tagName -> tagName + )); + public static TagName from(String tag) { - for (TagName tagName : TagName.values()) { - if (tagName.tag.equalsIgnoreCase(tag)) { - return tagName; - } - } + TagName tagName = TAG_MAP.get(tag.toLowerCase()); + if (tagName != null) { + return tagName; + } throw new InvalidStateException(TAG_NAME_NOT_MATCH); }src/main/java/konkuk/thip/user/domain/Alias.java (1)
16-22: static factory method 네이밍을 더 명확하게 할 수 있습니다.현재
from메서드는 세 개의 파라미터를 받는데, 메서드명이 너무 일반적입니다. 더 구체적인 이름을 고려해보세요.- public static Alias from(String value, String imageUrl, String color) { + public static Alias of(String value, String imageUrl, String color) {또는
- public static Alias from(String value, String imageUrl, String color) { + public static Alias create(String value, String imageUrl, String color) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
src/main/java/konkuk/thip/common/exception/code/ErrorCode.java(2 hunks)src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedTagJpaEntity.java(1 hunks)src/main/java/konkuk/thip/feed/adapter/out/mapper/FeedMapper.java(2 hunks)src/main/java/konkuk/thip/feed/adapter/out/mapper/TagMapper.java(0 hunks)src/main/java/konkuk/thip/feed/domain/Feed.java(2 hunks)src/main/java/konkuk/thip/feed/domain/Tag.java(1 hunks)src/main/java/konkuk/thip/feed/domain/TagName.java(1 hunks)src/main/java/konkuk/thip/user/adapter/in/web/request/UserSignupRequest.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java(0 hunks)src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java(2 hunks)src/main/java/konkuk/thip/user/application/port/in/dto/UserSignupCommand.java(1 hunks)src/main/java/konkuk/thip/user/application/service/UserSignupService.java(1 hunks)src/main/java/konkuk/thip/user/domain/Alias.java(1 hunks)src/main/java/konkuk/thip/user/domain/AliasName.java(1 hunks)src/main/java/konkuk/thip/user/domain/User.java(1 hunks)
💤 Files with no reviewable changes (2)
- src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java
- src/main/java/konkuk/thip/feed/adapter/out/mapper/TagMapper.java
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/main/java/konkuk/thip/user/domain/Alias.java (1)
src/main/java/konkuk/thip/user/domain/User.java (1)
Getter(7-34)
src/main/java/konkuk/thip/user/domain/AliasName.java (2)
src/main/java/konkuk/thip/user/domain/Alias.java (1)
Getter(6-23)src/main/java/konkuk/thip/user/domain/User.java (1)
Getter(7-34)
src/main/java/konkuk/thip/feed/domain/Tag.java (1)
src/main/java/konkuk/thip/feed/domain/Feed.java (1)
Getter(9-39)
src/main/java/konkuk/thip/feed/domain/TagName.java (1)
src/main/java/konkuk/thip/feed/domain/Tag.java (1)
Getter(6-18)
🔇 Additional comments (23)
src/main/java/konkuk/thip/user/application/port/in/dto/UserSignupCommand.java (1)
7-7: 필드 타입 변경이 적절합니다.
Long aliasId에서String aliasName으로의 변경이 리팩토링 목적에 부합하며, 도메인 모델의 Enum 기반 접근 방식과 일관성을 유지합니다.src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java (2)
6-6: 도메인 객체 import 추가가 적절합니다.
Alias도메인 클래스의 import가 아래 매핑 로직 변경과 일관성을 유지합니다.
30-32: 풍부한 도메인 객체 생성으로 개선되었습니다.기존 단순
aliasId할당에서Alias.from()메서드를 사용하여 전체 도메인 객체를 생성하는 방식으로 변경되어, 도메인 모델의 의도가 더 명확하게 표현됩니다.src/main/java/konkuk/thip/user/application/service/UserSignupService.java (1)
26-26: Alias 객체 생성 방식 변경이 적절합니다.
Alias.from(command.aliasName())호출로 변경하여 ID 기반 조회에서 직접 생성으로 전환한 것이 리팩토링 목적에 부합합니다.src/main/java/konkuk/thip/feed/domain/Feed.java (3)
7-7: List import 추가가 적절합니다.
List<Tag> tagList필드 추가를 위한 import가 적절합니다.
25-25: 태그 기능 지원을 위한 도메인 모델 확장
List<Tag> tagList필드 추가로 Feed 도메인에 태그 기능이 적절히 통합되었습니다.
27-37: 완전한 정적 팩토리 메서드 구현
withoutId메서드가 새로 추가된tagList필드를 포함하여 모든 필드를 적절히 초기화하고 있습니다.src/main/java/konkuk/thip/feed/domain/TagName.java (1)
8-24: 태그 상수 정의가 적절하게 구성되어 있습니다.15개의 태그 상수가 잘 정의되어 있고, 각각 한글 라벨을 가지고 있어 가독성이 좋습니다.
src/main/java/konkuk/thip/user/domain/Alias.java (2)
6-8: 도메인 모델 단순화가 적절합니다.BaseDomainEntity 상속을 제거하고 @builder로 변경한 것은 도메인 모델의 단순화 관점에서 적절한 변경입니다.
10-14: AliasName enum 타입 사용이 타입 안전성을 향상시킵니다.String에서 AliasName enum으로 변경하여 타입 안전성과 유효성 검증이 컴파일 타임에 보장됩니다.
src/main/java/konkuk/thip/feed/domain/Tag.java (3)
6-8: 도메인 모델 단순화가 적절합니다.BaseDomainEntity 상속을 제거하고 @builder로 변경한 것은 도메인 모델의 단순화 관점에서 적절한 변경입니다.
10-10: TagName enum 타입 사용이 타입 안전성을 향상시킵니다.String에서 TagName enum으로 변경하여 유효하지 않은 태그 값의 사용을 컴파일 타임에 방지할 수 있습니다.
12-16: static factory method 구현이 적절합니다.TagName.from()을 통해 유효성 검증을 위임하고, 실패 시 적절한 예외를 던지는 구조가 잘 구현되어 있습니다.
src/main/java/konkuk/thip/feed/adapter/out/mapper/FeedMapper.java (3)
5-12: 필요한 import들이 적절하게 추가되었습니다.Tag 도메인 매핑을 위한 import들이 적절하게 추가되었습니다.
28-28: 메서드 시그니처 변경이 적절합니다.TagJpaEntity 리스트를 받아 도메인 Tag 객체들로 변환하는 로직이 명확하게 구현되었습니다.
36-39: 태그 매핑 로직이 효율적으로 구현되었습니다.Stream API를 사용하여 TagJpaEntity에서 도메인 Tag로 변환하는 로직이 간결하고 효율적으로 구현되었습니다.
src/main/java/konkuk/thip/user/adapter/in/web/request/UserSignupRequest.java (3)
3-5: 적절한 validation import가 추가되었습니다.String 타입의 aliasName에 맞는 @notblank validation을 위한 import가 적절하게 추가되었습니다.
9-10: validation 어노테이션이 적절하게 변경되었습니다.Long 타입의 aliasId에서 String 타입의 aliasName으로 변경하면서 @NotNull에서 @notblank로 변경한 것이 적절합니다.
16-22: toCommand 메서드 매핑이 올바르게 수정되었습니다.새로운 aliasName 필드를 UserSignupCommand로 매핑하는 로직이 정확하게 구현되었습니다.
src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedTagJpaEntity.java (1)
1-26: 새로운 Feed-Tag 연결 엔티티가 잘 설계되었습니다.Feed와 Tag 간의 다대다 관계를 위한 연결 테이블 엔티티가 적절히 구현되었습니다. JPA 어노테이션과 Lazy loading 설정이 올바르게 적용되었습니다.
src/main/java/konkuk/thip/common/exception/code/ErrorCode.java (3)
33-33: 새로운 별칭 에러 코드가 적절히 추가되었습니다.
ALIAS_NAME_NOT_MATCH에러 코드가 60000대 별칭 에러 범위에 올바르게 추가되었습니다. HTTP 상태 코드와 메시지도 적절합니다.
105-105: trailing comma 추가가 좋은 변경입니다.
CATEGORY_NOT_FOUND뒤에 쉼표를 추가한 것은 향후 새로운 에러 코드 추가 시 diff를 깔끔하게 만드는 좋은 관례입니다.
107-111: 새로운 Feed 에러 카테고리가 잘 구성되었습니다.160000대 범위에 Feed 관련 에러 코드들이 체계적으로 추가되었습니다. 각 에러 코드의 HTTP 상태 코드와 메시지가 적절하게 설정되었습니다.
src/main/java/konkuk/thip/user/application/service/UserSignupService.java
Outdated
Show resolved
Hide resolved
| WRITER("문학가"), | ||
| SCIENTIST("과학자"), | ||
| SOCIOLOGIST("사회학자"), | ||
| ARTIEST("예술가"), |
There was a problem hiding this comment.
상수 이름 오타 수정 필요
ARTIEST는 ARTIST로 수정되어야 합니다.
다음 diff를 적용하여 오타를 수정하세요:
- ARTIEST("예술가"),
+ ARTIST("예술가"),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ARTIEST("예술가"), | |
| ARTIST("예술가"), |
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/domain/AliasName.java at line 12, the enum
constant name ARTIEST is misspelled and should be corrected to ARTIST. Rename
the constant from ARTIEST to ARTIST to fix the typo.
src/main/java/konkuk/thip/feed/adapter/out/mapper/FeedMapper.java
Outdated
Show resolved
Hide resolved
| public static User withoutId(String nickname, String imageUrl, String userRole, Long aliasId, String oauth2Id) { | ||
| private AliasName alias; | ||
|
|
||
| public static User withoutId(String nickname, String imageUrl, String userRole, String oauth2Id, Alias alias) { |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
메서드 시그니처 변경으로 인한 영향 확인 필요.
withoutId 메서드의 파라미터 순서가 변경되었습니다. 이 메서드를 사용하는 모든 곳에서 파라미터 순서가 올바르게 업데이트되었는지 확인해주세요.
🏁 Script executed:
#!/bin/bash
# withoutId 메서드 사용처 확인
rg -A 5 "withoutId" --type javaLength of output: 28055
🏁 Script executed:
#!/bin/bash
# withoutId 메서드 시그니처 및 빌더 호출 확인
sed -n '1,200p' src/main/java/konkuk/thip/user/domain/User.java | rg -C3 "withoutId"Length of output: 321
UserSignupService에서 User.withoutId 호출 파라미터 순서 수정 필요
현재 User.withoutId 시그니처는
public static User withoutId(
String nickname,
String imageUrl,
String userRole,
String oauth2Id,
Alias alias
)인데, 호출부에서는 alias.getId()가 oauth2Id로 잘못 전달되고 있습니다.
- File: src/main/java/konkuk/thip/user/application/service/UserSignupService.java
- User user = User.withoutId(
- command.nickname(),
- alias.getImageUrl(),
- USER.getType(),
- alias.getId(),
- command.oauth2Id()
- );
+ User user = User.withoutId(
+ command.nickname(),
+ alias.getImageUrl(),
+ USER.getType(),
+ command.oauth2Id(),
+ alias
+ );위와 같이 파라미터 순서를 맞춰 수정해주세요.
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/application/service/UserSignupService.java,
adjust the argument order when calling User.withoutId to match its signature in
src/main/java/konkuk/thip/user/domain/User.java at line 23. Specifically, ensure
that the oauth2Id parameter receives the correct OAuth2 ID value and the alias
parameter receives the Alias object, avoiding passing alias.getId() as oauth2Id.
| private String oauth2Id; | ||
|
|
||
| public static User withoutId(String nickname, String imageUrl, String userRole, Long aliasId, String oauth2Id) { | ||
| private AliasName alias; |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
타입 불일치 문제가 있습니다.
필드 타입이 AliasName으로 선언되었지만, 메서드 파라미터는 Alias 타입을 받고 있습니다. 타입 일관성을 확인해주세요.
- private AliasName alias;
+ private Alias alias;또는
- public static User withoutId(String nickname, String imageUrl, String userRole, String oauth2Id, Alias alias) {
+ public static User withoutId(String nickname, String imageUrl, String userRole, String oauth2Id, AliasName alias) {다음 스크립트를 실행하여 타입 일관성을 확인해주세요:
🏁 Script executed:
#!/bin/bash
# AliasName과 Alias 타입의 사용 패턴 확인
rg -A 3 "AliasName|Alias" --type javaLength of output: 67157
alias 필드와 withoutId 메서드 파라미터 타입 불일치 수정 필요
User 도메인에서 alias 필드는 AliasName으로 선언되어 있는데, withoutId 메서드는 여전히 Alias를 받고 있어 컴파일 오류가 발생합니다. 아래 위치들을 함께 수정해주세요.
• src/main/java/konkuk/thip/user/domain/User.java
- static 메서드 시그니처: 마지막 파라미터를
Alias→AliasName으로 변경 - 메서드 바디:
.alias(alias.getValue())→.alias(alias)으로 교체
• src/main/java/konkuk/thip/user/application/service/UserSignupService.java
User.withoutId(...)호출부 파라미터 순서 및 타입 조정
• 기존:User.withoutId(nickname, alias.getImageUrl(), USER.getType(), alias.getId(), command.oauth2Id())
• 수정:User.withoutId(nickname, alias.getImageUrl(), USER.getType(), command.oauth2Id(), alias.getValue())
예시 변경안:
--- a/src/main/java/konkuk/thip/user/domain/User.java
+++ b/src/main/java/konkuk/thip/user/domain/User.java
- public static User withoutId(String nickname, String imageUrl, String userRole, String oauth2Id, Alias alias) {
+ public static User withoutId(String nickname, String imageUrl, String userRole, String oauth2Id, AliasName alias) {
return User.builder()
.id(null)
.nickname(nickname)
.imageUrl(imageUrl)
.userRole(userRole)
.oauth2Id(oauth2Id)
- .alias(alias.getValue())
+ .alias(alias)
.build();
}--- a/src/main/java/konkuk/thip/user/application/service/UserSignupService.java
+++ b/src/main/java/konkuk/thip/user/application/service/UserSignupService.java
- User user = User.withoutId(
- command.nickname(),
- alias.getImageUrl(),
- USER.getType(),
- alias.getId(),
- command.oauth2Id()
- );
+ User user = User.withoutId(
+ command.nickname(),
+ alias.getImageUrl(),
+ USER.getType(),
+ command.oauth2Id(),
+ alias.getValue()
+ );🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/domain/User.java at line 21 and related code,
the alias field is declared as AliasName but the withoutId method still accepts
Alias, causing a type mismatch. Change the withoutId method's last parameter
type from Alias to AliasName and update its body to use .alias(alias) instead of
.alias(alias.getValue()). Also, in
src/main/java/konkuk/thip/user/application/service/UserSignupService.java,
adjust the User.withoutId call to match the new parameter order and types by
passing alias.getValue() as the last argument and command.oauth2Id() before it.
- 변경된 domain 구조로 인해, jpa -> domain 매핑 시 연관된 jpa의 지연로딩 기능을 사용해야할 때가 있는데, 이때 트랜잭션이 걸려있지않으면 error가 발생 - 도메인 엔티티를 조회하는 service 메서드에 모두 @transactional(readOnly = true) 추가
- 문학, 과학/IT 와 관련된 칭호, 카테고리 생성하도록 수정
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/main/java/konkuk/thip/user/domain/User.java (1)
19-28: 칭호 필드 타입 변경 승인 및 일관성 확인 필요
Aliasenum 타입으로 필드를 변경한 것은 리팩토링 방향에 맞습니다. 하지만 이전 리뷰 코멘트에서 지적된 타입 불일치 문제가 해결되었는지 확인이 필요합니다.현재 코드에서는 필드와 메서드 파라미터가 모두
Alias타입으로 일치하는 것으로 보이지만, 관련 서비스 레이어에서의 호출 부분도 함께 검토해주세요.
🧹 Nitpick comments (1)
src/main/java/konkuk/thip/user/domain/Alias.java (1)
21-28: from() 메서드 성능 최적화 제안현재 선형 검색을 사용하는
from()메서드는 enum 상수가 적을 때는 문제없지만, 성능 최적화를 위해 Map 기반 조회를 고려해볼 수 있습니다.+ private static final Map<String, Alias> VALUE_MAP = Arrays.stream(values()) + .collect(Collectors.toMap(Alias::getValue, Function.identity())); + public static Alias from(String value) { - for (Alias alias : Alias.values()) { - if (alias.value.equals(value)) { - return alias; - } - } - throw new InvalidStateException(ErrorCode.ALIAS_NAME_NOT_MATCH); + Alias alias = VALUE_MAP.get(value); + if (alias == null) { + throw new InvalidStateException(ErrorCode.ALIAS_NAME_NOT_MATCH); + } + return alias; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (45)
src/main/java/konkuk/thip/book/application/service/BookMostSearchRankService.java(2 hunks)src/main/java/konkuk/thip/book/application/service/BookMostSearchService.java(2 hunks)src/main/java/konkuk/thip/book/application/service/BookSearchService.java(3 hunks)src/main/java/konkuk/thip/common/exception/code/ErrorCode.java(2 hunks)src/main/java/konkuk/thip/record/adapter/in/web/response/RecordDto.java(1 hunks)src/main/java/konkuk/thip/record/adapter/in/web/response/VoteDto.java(1 hunks)src/main/java/konkuk/thip/record/application/service/RecordSearchService.java(2 hunks)src/main/java/konkuk/thip/room/application/service/RoomSearchService.java(3 hunks)src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java(1 hunks)src/main/java/konkuk/thip/user/adapter/in/web/response/UserViewAliasChoiceResponse.java(0 hunks)src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java(3 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/AliasCommandPersistenceAdapter.java(0 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/AliasJpaRepository.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/AliasQueryPersistenceAdapter.java(0 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/AliasQueryRepositoryImpl.java(0 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java(1 hunks)src/main/java/konkuk/thip/user/adapter/out/persistence/UserQueryPersistenceAdapter.java(3 hunks)src/main/java/konkuk/thip/user/application/port/in/dto/UserViewAliasChoiceResult.java(0 hunks)src/main/java/konkuk/thip/user/application/port/out/AliasCommandPort.java(0 hunks)src/main/java/konkuk/thip/user/application/port/out/AliasQueryPort.java(0 hunks)src/main/java/konkuk/thip/user/application/port/out/UserQueryPort.java(1 hunks)src/main/java/konkuk/thip/user/application/service/UserSignupService.java(1 hunks)src/main/java/konkuk/thip/user/application/service/UserViewAliasChoiceService.java(1 hunks)src/main/java/konkuk/thip/user/domain/Alias.java(1 hunks)src/main/java/konkuk/thip/user/domain/User.java(1 hunks)src/test/java/konkuk/thip/book/adapter/in/web/BookChangeSavedControllerTest.java(2 hunks)src/test/java/konkuk/thip/book/adapter/in/web/BookDetailSearchControllerTest.java(3 hunks)src/test/java/konkuk/thip/book/adapter/in/web/BookMostSearchedBooksControllerTest.java(2 hunks)src/test/java/konkuk/thip/book/adapter/in/web/BookQueryControllerTest.java(2 hunks)src/test/java/konkuk/thip/common/util/TestEntityFactory.java(1 hunks)src/test/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntityTest.java(1 hunks)src/test/java/konkuk/thip/record/adapter/in/web/RecordCreateControllerTest.java(1 hunks)src/test/java/konkuk/thip/record/adapter/in/web/RecordQueryControllerTest.java(3 hunks)src/test/java/konkuk/thip/record/adapter/out/persistence/RecordQueryRepositoryImplTest.java(4 hunks)src/test/java/konkuk/thip/record/application/service/RecordSearchServiceTest.java(6 hunks)src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateAPITest.java(4 hunks)src/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.java(9 hunks)src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java(4 hunks)src/test/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntityTest.java(1 hunks)src/test/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntityTest.java(1 hunks)src/test/java/konkuk/thip/room/adapter/out/jpa/VoteJpaEntityTest.java(1 hunks)src/test/java/konkuk/thip/user/adapter/in/web/UserSignupControllerTest.java(8 hunks)src/test/java/konkuk/thip/user/adapter/in/web/UserVerifyNicknameControllerTest.java(2 hunks)src/test/java/konkuk/thip/user/adapter/in/web/UserViewAliasChoiceControllerTest.java(2 hunks)src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java(2 hunks)
💤 Files with no reviewable changes (7)
- src/main/java/konkuk/thip/user/application/port/in/dto/UserViewAliasChoiceResult.java
- src/main/java/konkuk/thip/user/adapter/out/persistence/AliasQueryRepositoryImpl.java
- src/main/java/konkuk/thip/user/application/port/out/AliasCommandPort.java
- src/main/java/konkuk/thip/user/application/port/out/AliasQueryPort.java
- src/main/java/konkuk/thip/user/adapter/out/persistence/AliasCommandPersistenceAdapter.java
- src/main/java/konkuk/thip/user/adapter/in/web/response/UserViewAliasChoiceResponse.java
- src/main/java/konkuk/thip/user/adapter/out/persistence/AliasQueryPersistenceAdapter.java
✅ Files skipped from review due to trivial changes (9)
- src/test/java/konkuk/thip/book/adapter/in/web/BookChangeSavedControllerTest.java
- src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java
- src/main/java/konkuk/thip/record/application/service/RecordSearchService.java
- src/test/java/konkuk/thip/book/adapter/in/web/BookQueryControllerTest.java
- src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java
- src/test/java/konkuk/thip/book/adapter/in/web/BookDetailSearchControllerTest.java
- src/main/java/konkuk/thip/book/application/service/BookMostSearchService.java
- src/main/java/konkuk/thip/book/application/service/BookSearchService.java
- src/test/java/konkuk/thip/record/adapter/out/persistence/RecordQueryRepositoryImplTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
- src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java
- src/main/java/konkuk/thip/user/application/service/UserSignupService.java
- src/main/java/konkuk/thip/common/exception/code/ErrorCode.java
🧰 Additional context used
🧠 Learnings (7)
src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateAPITest.java (1)
Learnt from: hd0rable
PR: THIP-TextHip/THIP-Server#57
File: src/test/java/konkuk/thip/room/domain/RoomTest.java:0-0
Timestamp: 2025-07-08T16:30:33.756Z
Learning: Room 도메인에서 startDate는 현재 날짜 이후여야 하는 도메인 규칙이 있어서, 테스트에서 만료된 상태를 시뮬레이션하려면 reflection을 사용해야 한다.
src/main/java/konkuk/thip/user/adapter/out/persistence/AliasJpaRepository.java (2)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#36
File: src/main/java/konkuk/thip/user/adapter/out/persistence/UserJpaRepository.java:7-7
Timestamp: 2025-06-29T09:47:31.299Z
Learning: Spring Data JPA에서 findBy{FieldName} 패턴의 메서드는 명시적 선언 없이 자동으로 생성되며, Optional<Entity> 반환 타입을 사용하는 것이 null 안전성을 위해 권장됩니다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/user/application/port/out/UserQueryPort.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/test/java/konkuk/thip/record/application/service/RecordSearchServiceTest.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/user/adapter/out/persistence/UserQueryPersistenceAdapter.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/main/java/konkuk/thip/user/application/service/UserViewAliasChoiceService.java (1)
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
src/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.java (1)
Learnt from: hd0rable
PR: THIP-TextHip/THIP-Server#57
File: src/test/java/konkuk/thip/room/domain/RoomTest.java:0-0
Timestamp: 2025-07-08T16:30:33.756Z
Learning: Room 도메인에서 startDate는 현재 날짜 이후여야 하는 도메인 규칙이 있어서, 테스트에서 만료된 상태를 시뮬레이션하려면 reflection을 사용해야 한다.
🧬 Code Graph Analysis (14)
src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntityTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/record/adapter/in/web/RecordCreateControllerTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntityTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateAPITest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/room/adapter/out/jpa/VoteJpaEntityTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntityTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/user/adapter/in/web/UserVerifyNicknameControllerTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/record/adapter/in/web/RecordQueryControllerTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/test/java/konkuk/thip/book/adapter/in/web/BookMostSearchedBooksControllerTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/main/java/konkuk/thip/user/application/service/UserViewAliasChoiceService.java (2)
src/main/java/konkuk/thip/book/application/service/BookSearchService.java (1)
Service(33-145)src/main/java/konkuk/thip/user/application/service/UserVerifyNicknameService.java (1)
Service(8-18)
src/test/java/konkuk/thip/user/adapter/in/web/UserViewAliasChoiceControllerTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
src/main/java/konkuk/thip/user/domain/Alias.java (1)
src/main/java/konkuk/thip/user/domain/User.java (1)
Getter(7-31)
src/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
TestEntityFactory(16-115)
🔇 Additional comments (60)
src/main/java/konkuk/thip/book/application/service/BookMostSearchRankService.java (1)
15-15: @transactional 어노테이션 추가를 재검토해주세요.이 import는 아래 메서드에 추가된 @transactional 어노테이션을 위한 것으로 보입니다. 하지만 해당 메서드의 특성상 트랜잭션 적용에 대한 재검토가 필요합니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/AliasJpaRepository.java (2)
6-6: Optional import 추가 확인됨새로운
findByValue메소드의 반환 타입을 위해 적절히 import가 추가되었습니다.
10-10: 값 기반 조회 메소드 추가가 적절함ID 기반에서 값 기반으로의 도메인 변경에 맞춰
findByValue메소드가 올바르게 추가되었습니다. Spring Data JPA 컨벤션을 따르며 Optional 반환 타입으로 null 안전성을 확보한 좋은 구현입니다.src/test/java/konkuk/thip/common/util/TestEntityFactory.java (5)
18-21: 문서화 주석 추가 확인됨팩토리 클래스의 목적을 명확히 하는 주석이 추가되어 가독성이 향상되었습니다.
22-28: 문학 Alias 팩토리 메소드 구현 적절함실제 존재하는 값("문학가")으로 엔티티를 생성하는 구체적인 팩토리 메소드가 잘 구현되었습니다. 테스트 데이터의 일관성과 명확성을 높이는 좋은 변경사항입니다.
30-35: 문학 Category 팩토리 메소드 구현 적절함Alias와 연관된 Category 엔티티를 생성하는 메소드가 올바르게 구현되었습니다. 실제 존재하는 값("문학")을 사용하여 테스트 데이터의 신뢰성을 높였습니다.
37-43: 과학 Alias 팩토리 메소드 구현 적절함문학 Alias와 일관성 있는 패턴으로 과학 Alias 팩토리 메소드가 구현되었습니다. 실제 존재하는 값("과학자")을 사용하여 도메인 변경에 적절히 대응했습니다.
45-50: 과학 Category 팩토리 메소드 구현 적절함과학 분야의 Category 엔티티 생성 메소드가 올바르게 구현되었습니다. "과학/IT" 값을 사용하여 실제 도메인 데이터와 일치하는 테스트 데이터를 생성합니다.
src/test/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntityTest.java (2)
55-55: 구체적인 팩토리 메소드 사용으로 개선됨
createAlias()에서createLiteratureAlias()로 변경하여 테스트 데이터 생성이 더 명확하고 일관성 있게 되었습니다.
58-58: 연관된 Category 팩토리 메소드 사용 적절함
createCategory(alias)에서createLiteratureCategory(alias)로 변경하여 Alias와 Category 간의 관계를 명확히 하는 좋은 개선사항입니다.src/test/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntityTest.java (1)
46-46: 구체적인 팩토리 메소드 사용으로 일관성 확보
createAlias()에서createLiteratureAlias()로 변경하여 다른 테스트 파일들과 일관성 있는 테스트 데이터 생성 방식을 적용했습니다.src/test/java/konkuk/thip/user/adapter/in/web/UserVerifyNicknameControllerTest.java (2)
5-5: TestEntityFactory import 추가 확인됨팩토리 메소드 사용을 위한 import가 적절히 추가되었습니다.
80-80: 팩토리 메소드 사용으로 테스트 코드 개선수동으로 alias 엔티티를 생성하던 방식에서
TestEntityFactory.createLiteratureAlias()사용으로 변경하여 테스트 코드의 일관성과 유지보수성이 향상되었습니다.src/test/java/konkuk/thip/book/adapter/in/web/BookMostSearchedBooksControllerTest.java (2)
6-6: 테스트 데이터 생성 표준화 개선사항 승인
TestEntityFactory.createLiteratureAlias()팩토리 메서드를 사용하여 테스트 데이터 생성을 표준화한 변경사항이 좋습니다. 이는 테스트 코드의 일관성과 유지보수성을 향상시킵니다.Also applies to: 66-66
6-6: 테스트 데이터 생성 표준화 - 좋은 개선사항입니다
TestEntityFactory.createLiteratureAlias()를 사용하여 테스트 데이터 생성을 표준화한 것은 좋은 변경입니다. 하드코딩된 값들을 팩토리 메서드로 추상화하여 테스트 코드의 가독성과 유지보수성이 향상되었습니다.Also applies to: 66-66
src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java (2)
36-36: 테스트 일관성 개선 승인
TestEntityFactory.createLiteratureAlias()를 사용하고 대응하는 assertion을 "문학가"로 업데이트한 변경사항이 일관성 있게 적용되었습니다. 별칭 도메인 리팩토링에 맞춰 테스트가 올바르게 수정되었습니다.Also applies to: 47-47
36-36: 일관된 팩토리 메서드 사용과 올바른 기대값 수정
createLiteratureAlias()팩토리 메서드 사용으로 변경하고, 이에 맞춰 기대값을 "문학가"로 수정한 것이 올바릅니다. 테스트 데이터와 검증 로직이 일관성 있게 업데이트되었습니다.Also applies to: 47-47
src/main/java/konkuk/thip/record/adapter/in/web/response/RecordDto.java (2)
32-32: 프로필 이미지 URL 접근 방식 변경 일관성 확인됨
user.getImageUrl()호출은 모두 제거되었으며, 다음 위치에서 일관되게user.getAlias().getImageUrl()호출을 사용하고 있습니다:
src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java(line 16)src/main/java/konkuk/thip/record/adapter/in/web/response/RecordDto.java(line 32)src/main/java/konkuk/thip/record/adapter/in/web/response/VoteDto.java(line 39)User 도메인 클래스에 Lombok
@Getter가 적용되어getAlias()가 제공되며, Alias 클래스 역시@Getter로imageUrl필드를 노출하고 있어getImageUrl()호출이 정상 동작합니다.
도메인 설계상 User 생성 시 Alias를 필수 인자로 받으므로 null 발생 가능성은 낮습니다. 추가로 런타임 상황에서 alias가 null인지 확인하고 싶다면, 매핑 전후에 null 체크를 넣어주세요.
32-32: 검증 완료: Alias를 통한 이미지 URL 접근 패턴 일관성 확인됨RecordDto, VoteDto, 그리고 UserMapper에서
user.getImageUrl()호출이 모두user.getAlias().getImageUrl()로 일관되게 변경된 것이 확인되었습니다.
누락된 참조 없이 모든 관련 코드가 올바르게 업데이트되었으므로 변경사항을 승인합니다.src/test/java/konkuk/thip/room/adapter/out/jpa/VoteJpaEntityTest.java (2)
55-55: 테스트 엔티티 생성 표준화 승인
TestEntityFactory.createLiteratureAlias()와TestEntityFactory.createLiteratureCategory(alias)를 사용하여 테스트 엔티티 생성을 표준화한 변경사항이 일관성 있게 적용되었습니다. 카테고리가 별칭을 매개변수로 받는 구조도 도메인 관계를 잘 반영하고 있습니다.Also applies to: 58-58
55-55: 테스트 데이터 생성의 일관된 표준화Alias와 Category 생성을 모두 문학 관련 팩토리 메서드로 통일한 것이 좋습니다. 테스트 데이터의 일관성과 의미가 더욱 명확해졌습니다.
Also applies to: 58-58
src/test/java/konkuk/thip/record/adapter/in/web/RecordCreateControllerTest.java (2)
84-84: 테스트 설정 메서드 표준화 승인
saveUserAndRoom()메서드에서TestEntityFactory.createLiteratureAlias()와TestEntityFactory.createLiteratureCategory(alias)를 사용하여 테스트 엔티티 생성을 표준화한 변경사항이 올바르게 적용되었습니다. 다른 테스트 파일들과 일관성 있는 패턴을 따르고 있습니다.Also applies to: 90-90
84-84: 테스트 설정의 일관된 표준화 완료다른 테스트 파일들과 일관되게 문학 관련 팩토리 메서드를 사용하도록 수정되었습니다. 전체 테스트 스위트에서 표준화된 테스트 데이터 생성 패턴이 잘 적용되었습니다.
Also applies to: 90-90
src/main/java/konkuk/thip/record/adapter/in/web/response/VoteDto.java (1)
39-39: 도메인 모델 리팩토링에 맞는 올바른 변경사항입니다.User 도메인에서 imageUrl 필드가 제거되고 Alias enum을 통해 프로필 이미지 URL을 가져오도록 변경된 것이 올바르게 반영되었습니다.
src/test/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntityTest.java (1)
47-48: 테스트 데이터 생성 방식이 개선되었습니다.일반적인 factory 메소드 대신 특화된
createLiteratureAlias()와createLiteratureCategory(alias)메소드를 사용하여 테스트 데이터의 일관성과 명확성이 향상되었습니다.src/main/java/konkuk/thip/user/application/port/out/UserQueryPort.java (1)
11-11: CQRS 패턴에 맞는 올바른 인터페이스 변경입니다.별도의 AliasQueryPort를 제거하고 UserQueryPort에 alias 조회 기능을 통합한 것이 CQRS 컨벤션에 맞으며, 코드 구조가 더 명확해졌습니다.
src/main/java/konkuk/thip/user/adapter/out/persistence/UserQueryPersistenceAdapter.java (2)
16-16: 새로운 의존성 주입이 적절합니다.AliasJpaRepository를 주입받아 alias 조회 기능을 구현하기 위한 적절한 변경사항입니다.
29-32: 포트 인터페이스 구현이 올바릅니다.UserQueryPort의 새로운 메소드를 repository에 위임하는 방식으로 올바르게 구현되었습니다.
src/test/java/konkuk/thip/record/application/service/RecordSearchServiceTest.java (5)
44-44: 테스트 구조 개선을 위한 적절한 필드 추가입니다.중복되는 User 목 객체 생성을 중앙화하기 위한 stubUser 필드 추가가 적절합니다.
56-59: 테스트 데이터 중앙화가 잘 구현되었습니다.일관된 Alias.WRITER와 userId를 가진 stubUser를 setUp에서 생성하여 테스트 전반에서 재사용할 수 있도록 개선되었습니다.
94-94: 중복 제거로 테스트 유지보수성이 향상되었습니다.인라인 목 객체 생성 대신 중앙화된 stubUser를 사용하여 테스트 코드의 일관성이 개선되었습니다.
135-135: 일관된 목 객체 사용이 적절합니다.동일한 stubUser를 재사용하여 테스트 간 일관성을 유지하고 있습니다.
174-174: 테스트 코드 중복 제거가 완료되었습니다.모든 테스트 메소드에서 동일한 stubUser를 사용하여 코드 중복을 효과적으로 제거했습니다.
src/test/java/konkuk/thip/record/adapter/in/web/RecordQueryControllerTest.java (3)
8-8: 테스트 엔티티 팩토리 import 추가 승인
TestEntityFactoryimport 추가로 테스트 엔티티 생성을 표준화하는 것이 좋습니다.
76-76: 팩토리 메서드를 통한 Alias 엔티티 생성 개선수동 엔티티 생성을
TestEntityFactory.createLiteratureAlias()팩토리 메서드로 대체하여 테스트 데이터 생성이 일관성 있게 개선되었습니다.
97-97: 팩토리 메서드를 통한 Category 엔티티 생성 개선수동 엔티티 생성을
TestEntityFactory.createLiteratureCategory(alias)팩토리 메서드로 대체하여 테스트 데이터 생성의 일관성이 향상되었습니다.src/main/java/konkuk/thip/user/adapter/out/persistence/UserCommandPersistenceAdapter.java (1)
26-27: Alias 조회 메서드 정의 확인 및 변경 승인
src/main/java/konkuk/thip/user/adapter/out/persistence/AliasJpaRepository.java에서
Optional<AliasJpaEntity> findByValue(String value);가 정상 정의되어 있습니다.- 값 기반 조회 리팩토링이 의도대로 반영되었으며 예외 처리 로직도 적절히 유지되고 있습니다.
해당 변경 사항을 승인합니다.
src/main/java/konkuk/thip/user/application/service/UserViewAliasChoiceService.java (3)
5-5: Port 통합을 위한 import 변경 승인
AliasQueryPort에서UserQueryPort로 import 변경이 포트 통합 목표와 일치합니다.
13-13: 포트 의존성 통합 승인
AliasQueryPort를UserQueryPort로 통합하여 포트 인터페이스 수를 줄이고 관련 기능을 응집시킨 것이 좋습니다.
17-17: 메서드 호출 위임 변경 승인
aliasQueryPort에서userQueryPort로 메서드 호출 위임을 변경하여 포트 통합이 완료되었습니다.src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateAPITest.java (5)
7-7: 테스트 엔티티 팩토리 import 추가 승인
TestEntityFactoryimport 추가로 테스트 엔티티 생성을 표준화하는 것이 좋습니다.
76-76: 팩토리 메서드를 통한 Alias 엔티티 생성 개선수동 엔티티 생성을
TestEntityFactory.createLiteratureAlias()팩토리 메서드로 대체하여 테스트 데이터 생성이 일관성 있게 개선되었습니다.
86-86: 팩토리 메서드를 통한 Category 엔티티 생성 개선수동 엔티티 생성을
TestEntityFactory.createLiteratureCategory(alias)팩토리 메서드로 대체하여 테스트 데이터 생성의 일관성이 향상되었습니다.
118-118: 테스트 데이터 카테고리 변경 확인카테고리를 "과학/IT"에서 "문학"으로 변경한 것이 팩토리 메서드에서 생성하는 문학 카테고리와 일치합니다.
122-122: 테스트 기간 단축 승인
progressEndDate를 30일에서 10일로 단축하여 테스트 실행 시간을 최적화한 것이 좋습니다.src/test/java/konkuk/thip/user/adapter/in/web/UserViewAliasChoiceControllerTest.java (3)
5-5: 테스트 엔티티 팩토리 import 추가 승인
TestEntityFactoryimport 추가로 테스트 엔티티 생성을 표준화하는 것이 좋습니다.
77-79: 팩토리 데이터와 일치하는 기대값 수정 승인팩토리 메서드에서 생성하는 데이터와 일치하도록 기대값을 수정한 것이 좋습니다:
- 이미지 URL: "문학_image", "과학_image"
- 색상: "문학_color", "과학_color"
테스트 데이터의 일관성이 확보되었습니다.
83-87: 팩토리 메서드를 통한 엔티티 생성 개선수동 엔티티 생성을
TestEntityFactory팩토리 메서드들로 대체하여 테스트 데이터 생성이 일관성 있게 개선되었습니다. 코드 중복도 제거되고 유지보수성이 향상되었습니다.src/main/java/konkuk/thip/room/application/service/RoomSearchService.java (2)
29-29: 읽기 전용 트랜잭션 어노테이션 추가 승인검색 메서드에
@Transactional(readOnly = true)어노테이션을 추가한 것은 적절합니다. 읽기 전용 작업에 대한 성능 최적화와 명확한 의도 표현에 도움이 됩니다.
59-65: 카테고리 검증 로직 단순화 승인try-catch 블록을 제거하고
Category.from(category).getValue()을 직접 호출하는 것으로 단순화한 것이 좋습니다. 이는 도메인 enum에서 예외 처리를 담당하는 일관된 패턴을 따르고 있습니다.src/main/java/konkuk/thip/user/domain/Alias.java (1)
10-19: 칭호 도메인을 enum으로 리팩토링한 것 승인ID 기반 엔티티에서 고정된 enum 상수로 변경한 것은 매우 적절합니다. 칭호가 미리 정의된 고정 값들이라는 도메인 특성을 잘 반영하고 있으며, 불변성과 타입 안전성을 보장합니다.
src/test/java/konkuk/thip/user/adapter/in/web/UserSignupControllerTest.java (4)
6-6: TestEntityFactory 사용 승인중앙화된 테스트 엔티티 팩토리를 사용하도록 변경한 것은 테스트 코드의 유지보수성과 일관성을 크게 향상시킵니다.
62-67: 칭호 ID에서 칭호 이름으로 변경 승인도메인 리팩토링에 맞춰
aliasId대신aliasName을 사용하도록 테스트 요청을 업데이트한 것이 적절합니다. enum 기반 칭호 모델과 일관성을 유지하고 있습니다.
85-89: 테스트 검증 로직 업데이트 승인칭호 검증 로직을 ID 기반에서 값 기반으로 변경한 것이 올바릅니다.
findByValue()메서드 사용과aliasName()비교가 새로운 도메인 모델과 일치합니다.
108-108: 에러 메시지 및 테스트 데이터 업데이트 승인모든 테스트 케이스에서 칭호 관련 데이터를 ID에서 이름으로 일관되게 업데이트한 것이 좋습니다. 에러 메시지도 "aliasName은 필수입니다"로 적절히 변경되었습니다.
Also applies to: 116-116, 136-136, 156-156, 213-213
src/test/java/konkuk/thip/room/adapter/in/web/RoomSearchApiTest.java (5)
5-5: TestEntityFactory 사용 승인중앙화된 테스트 엔티티 팩토리를 import하여 사용하는 것은 테스트 코드의 일관성과 유지보수성을 향상시킵니다.
71-98: 과학 카테고리 전용 방 생성 메서드 승인
saveScienceRoom()메서드를 추가하여 과학 카테고리 방 생성을 전담하도록 한 것이 좋습니다.TestEntityFactory.createScienceAlias()와TestEntityFactory.createScienceCategory()를 사용하여 테스트 데이터 생성을 표준화한 것도 적절합니다.
100-127: 문학 카테고리 전용 방 생성 메서드 승인
saveLiteratureRoom()메서드를 추가하여 문학 카테고리 방 생성을 전담하도록 한 것이 좋습니다. 과학 카테고리와 동일한 패턴으로TestEntityFactory를 활용하여 일관성을 유지하고 있습니다.
130-130: 사용자 생성 메서드 팩토리 사용 승인
saveUsersToRoom()메서드에서도TestEntityFactory.createScienceAlias()를 사용하도록 업데이트한 것이 일관성 있습니다.
161-177: 테스트 케이스 업데이트 승인각 테스트 케이스에서 적절한 전용 메서드(
saveScienceRoom(),saveLiteratureRoom())를 사용하도록 업데이트한 것이 테스트 의도를 명확하게 표현합니다. 테스트 로직은 그대로 유지하면서 가독성이 향상되었습니다.
| // 매일 0시 실행 | ||
| @Async | ||
| @Scheduled(cron = "0 0 0 * * *") | ||
| @Transactional |
There was a problem hiding this comment.
@async와 @transactional 조합 및 트랜잭션 경계를 재검토해주세요.
이 메서드에 @transactional을 추가하는 것은 다음과 같은 이유로 문제가 될 수 있습니다:
- @async와 @transactional 조합 문제: 비동기 메서드에서 트랜잭션이 예상대로 작동하지 않을 수 있습니다.
- 혼합된 데이터 저장소: Redis 연산과 데이터베이스 연산이 함께 있어 트랜잭션 경계가 명확하지 않습니다.
- 외부 API 호출: 트랜잭션 내에서 외부 API(Naver API)를 호출하면 긴 트랜잭션이 될 수 있습니다.
- 스케줄링된 작업: 장기간 실행되는 트랜잭션은 리소스 경합을 유발할 수 있습니다.
다음 중 하나의 접근 방식을 고려해보세요:
-@Async
-@Scheduled(cron = "0 0 0 * * *")
-@Transactional
-public void updateDailySearchRank() {
+@Async
+@Scheduled(cron = "0 0 0 * * *")
+public void updateDailySearchRank() {
// Redis 연산들 (트랜잭션 불필요)
// ...
// 데이터베이스 연산만 별도 트랜잭션 메서드로 분리
+ processBookDetails(isbns);
+}
+
+@Transactional
+private void processBookDetails(List<String> isbns) {
// 데이터베이스 관련 연산만 여기에
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Transactional | |
| @Async | |
| @Scheduled(cron = "0 0 0 * * *") | |
| public void updateDailySearchRank() { | |
| // Redis 연산들 (트랜잭션 불필요) | |
| // ... | |
| // 데이터베이스 연산만 별도 트랜잭션 메서드로 분리 | |
| processBookDetails(isbns); | |
| } | |
| @Transactional | |
| private void processBookDetails(List<String> isbns) { | |
| // 데이터베이스 관련 연산만 여기에 | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/konkuk/thip/book/application/service/BookMostSearchRankService.java
at line 35, the use of @Transactional on a method annotated with @Async is
problematic due to transaction boundaries not working as expected, mixed Redis
and DB operations, external API calls, and long-running scheduled tasks. To fix
this, remove the @Transactional annotation from the async method and instead
manage transactions explicitly in smaller, synchronous service methods that
handle database operations only. Ensure Redis operations and external API calls
are outside transactional boundaries to avoid long transactions and resource
contention.
- Redis에서는 Trasactional 적용 x - Async에서는 Trasactional 정상 동작안 될 수 있음
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/main/java/konkuk/thip/feed/domain/Tag.java (3)
8-8: enum에서 @Getter 어노테이션 사용 검토 필요enum에서 Lombok의 @Getter 어노테이션 사용이 필요한지 검토해보세요. 현재
tag필드만 존재하므로 명시적인 getter 메서드를 작성하거나 필드를 public으로 선언하는 것이 더 명확할 수 있습니다.-@Getter -public enum Tag { +public enum Tag { // enum constants... - private final String tag; + private final String tag; Tag(String tag) { this.tag = tag; } + + public String getTag() { + return tag; + }
10-24: 태그 상수들의 그룹핑 및 순서 개선 제안현재 태그들이 특별한 순서 없이 나열되어 있습니다. 관련성이 높은 태그들끼리 그룹핑하면 가독성과 유지보수성이 향상될 수 있습니다.
public enum Tag { + // 일반적인 독서 활동 BOOK_RECOMMEND("책추천"), - TODAYS_BOOK("오늘의책"), READING_LOG("독서기록"), BOOK_REVIEW("책리뷰"), - QUOTE("책속한줄"), BOOK_REPORT("독후감"), + QUOTE("책속한줄"), + TODAYS_BOOK("오늘의책"), + + // 개인적 선호 LIFE_BOOK("내인생책"), RE_READ("다시읽고싶은책"), - BOOK_TALK("북토크"), + + // 소셜 활동 + BOOK_TALK("북토크"), BOOKSTAGRAM("책스타그램"), + + // 장르별 추천 NOVEL("소설추천"), SELF_IMPROVEMENT("자기계발서"), PHILOSOPHY("인문학책"), SCIENCE("과학책"), ECONOMY("경제책");
32-39: from 메서드 성능 최적화 제안현재
from메서드는 O(n) 시간복잡도로 모든 enum 값을 순회합니다. 정적 Map을 사용하여 O(1) 조회 성능으로 개선할 수 있습니다.+import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.Arrays; public enum Tag { // enum constants... private final String tag; + + private static final Map<String, Tag> TAG_MAP = Arrays.stream(values()) + .collect(Collectors.toMap( + tag -> tag.tag.toLowerCase(), + Function.identity() + )); Tag(String tag) { this.tag = tag; } public static Tag from(String tag) { - for (Tag tagName : Tag.values()) { - if (tagName.tag.equalsIgnoreCase(tag)) { - return tagName; - } - } - throw new InvalidStateException(TAG_NAME_NOT_MATCH); + Tag foundTag = TAG_MAP.get(tag.toLowerCase()); + if (foundTag == null) { + throw new InvalidStateException(TAG_NAME_NOT_MATCH); + } + return foundTag; } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/konkuk/thip/feed/adapter/out/mapper/FeedMapper.java(2 hunks)src/main/java/konkuk/thip/feed/domain/Tag.java(1 hunks)src/main/java/konkuk/thip/room/domain/Category.java(1 hunks)src/main/java/konkuk/thip/user/domain/Alias.java(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/main/java/konkuk/thip/room/domain/Category.java
🚧 Files skipped from review as they are similar to previous changes (2)
- src/main/java/konkuk/thip/feed/adapter/out/mapper/FeedMapper.java
- src/main/java/konkuk/thip/user/domain/Alias.java
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#43
File: src/main/java/konkuk/thip/book/application/port/out/BookCommandPort.java:0-0
Timestamp: 2025-07-03T03:05:05.031Z
Learning: THIP 프로젝트에서는 CQRS Port 분리 시 다음 컨벤션을 따름: CommandPort에는 findByXXX를 통해 도메인 엔티티를 찾아오는 메서드를 추가하고, QueryPort에는 조회 API의 response에 해당하는 데이터들을 DB로부터 조회하는 메서드를 추가함.
🧬 Code Graph Analysis (1)
src/main/java/konkuk/thip/feed/domain/Tag.java (1)
src/main/java/konkuk/thip/feed/domain/Feed.java (1)
Getter(9-39)
🔇 Additional comments (1)
src/main/java/konkuk/thip/feed/domain/Tag.java (1)
9-40: 도메인 모델 변경에 대한 전반적 평가Tag를 엔티티에서 enum으로 변경한 것은 훌륭한 리팩토링입니다. 고정된 태그 집합을 다루는 데 enum이 더 적합하며, 타입 안전성과 성능 모두 향상됩니다. AI 요약에서 언급된 대로 Feed 도메인의
List<Tag> tagList와도 잘 연동될 것으로 보입니다.
|



#️⃣ 연관된 이슈
📝 작업 내용
📸 스크린샷
💬 리뷰 요구사항
📌 PR 진행 시 이러한 점들을 참고해 주세요
Summary by CodeRabbit
신규 기능
버그 수정
리팩터링
테스트
스타일