-
Notifications
You must be signed in to change notification settings - Fork 2
♻️ [refactor] - 상세 주소를 위해 Region 엔티티를 리팩토링한다 #64
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
Conversation
WalkthroughRegion 엔티티를 상세 주소 구조로 재설계하고 지역 식별 방식을 이름→ID로 전환했다. 회원가입/구글가입/유저정보수정 DTO와 서비스 로직이 regionId 기반으로 변경되었고, 지역 검색 API·페이지 응답 DTO·보안 설정·Flyway 초기 마이그레이션이 추가되었다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Client
participant RC as RegionController
participant S as RegionQueryService
participant R as RegionRepository
rect rgb(245,248,255)
note over C,RC: 지역 검색 요청 (GET /api/regions?searchKeyword=...&page=...)
C->>RC: searchRegion(keyword, page)
RC->>S: searchRegion(keyword, page)
S->>S: trim keyword, PageRequest(size=10)
S->>R: searchByKeywordIgnoreCase(keyword, pageable)
R-->>S: Page<Region>
S->>S: map -> List<SearchRegionDto>
S-->>RC: PageResponseDto<SearchRegionDto>
RC-->>C: 200 OK (PageResponseDto)
end
sequenceDiagram
autonumber
participant C as Client
participant AS as AuthService
participant RS as RegionQueryService
note over C,AS: 회원가입/구글가입/정보수정 흐름 (region name → regionId)
C->>AS: signUp / googleSignUp / updateUserInfo (regionId)
AS->>RS: findRegionById(regionId)
RS-->>AS: Region
AS-->>C: 처리 완료 (회원 생성/업데이트)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used🧬 Code graph analysis (1)src/main/java/com/example/dgu/returnwork/domain/auth/dto/request/GoogleSignUpRequestDto.java (3)
🔇 Additional comments (2)
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. Comment |
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: 2
🧹 Nitpick comments (10)
src/main/resources/application-local.yml (1)
23-26: YAML 포맷 수정 권장.Flyway 설정이 올바르게 추가되었습니다.
baseline-on-migrate: true설정은 기존 데이터베이스에 마이그레이션을 적용할 때 유용합니다.다만, YAMLlint에서 콜론 앞 공백이 과도하다는 경고가 있습니다. 일관성을 위해 다음과 같이 수정하는 것을 권장합니다:
flyway: - enabled : true + enabled: true baseline-on-migrate: true - locations : classpath:db/migration + locations: classpath:db/migrationsrc/main/resources/db/migration/V1__create_tables.sql (2)
3-11: 검색 성능을 위한 인덱스 추가 권장.
regions테이블의search_keywords필드를 기반으로 검색이 이루어질 것으로 보이는데, 검색 성능 향상을 위해 인덱스 추가를 고려하시기 바랍니다.다음과 같은 인덱스를 추가할 수 있습니다:
CREATE INDEX idx_regions_search_keywords ON regions(search_keywords);또는 FULLTEXT 인덱스가 더 적합할 수 있습니다:
CREATE FULLTEXT INDEX idx_regions_fulltext ON regions(search_keywords);
138-138: 파일 끝에 개행 추가 권장.SQL 파일 끝에 개행 문자가 없습니다. 일부 도구와의 호환성 및 Git diff의 가독성을 위해 파일 끝에 개행을 추가하는 것이 좋습니다.
CONSTRAINT FK7t0qlyrlnhn8xjj1atdwtevad FOREIGN KEY (region_id) REFERENCES regions (id) - ); + ); +src/main/java/com/example/dgu/returnwork/domain/auth/dto/request/SignUpRequestDto.java (1)
36-37: regionId에 유효성 검증 추가를 고려하세요.regionId 필드가 필수값인 경우
@NotNull검증을 추가하는 것이 좋습니다. 다른 필수 필드들은@NotBlank를 사용하고 있지만, regionId는 검증 어노테이션이 없어 null 값이 허용됩니다.다음 diff를 적용하여 검증을 추가할 수 있습니다:
+ @NotNull(message = "지역은 필수입니다") @Schema(example = "1") Long regionId,src/main/java/com/example/dgu/returnwork/domain/auth/dto/request/GoogleSignUpRequestDto.java (1)
25-26: regionId에 유효성 검증 추가를 고려하세요.SignUpRequestDto와 동일하게, regionId가 필수값인 경우
@NotNull검증을 추가하는 것이 좋습니다.다음 diff를 적용하여 검증을 추가할 수 있습니다:
+ @NotNull(message = "지역은 필수입니다") @Schema(example = "1") Long regionId,src/main/java/com/example/dgu/returnwork/domain/region/service/RegionQueryService.java (2)
26-34: trim 후 빈 문자열 검증을 고려하세요.Line 28에서 keyword를 trim하지만, trim 후 빈 문자열인지 확인하지 않습니다. 공백만 입력된 경우 데이터베이스에 불필요한 쿼리가 실행될 수 있습니다.
다음과 같이 검증을 추가할 수 있습니다:
public PageResponseDto<SearchRegionDto> searchRegion(String keyword, Integer page){ String trimKeyword = keyword.trim(); + + if (trimKeyword.isEmpty()) { + return PageResponseDto.from(Page.empty()); + } Pageable pageable = PageRequest.of(page, 10);
30-30: 페이지 크기를 설정 가능하도록 고려하세요.페이지 크기가 10으로 고정되어 있습니다. 향후 확장성을 위해 상수로 추출하거나 설정 파일에서 관리하는 것을 고려해보세요.
예시:
+ private static final int DEFAULT_PAGE_SIZE = 10; + public PageResponseDto<SearchRegionDto> searchRegion(String keyword, Integer page){ String trimKeyword = keyword.trim(); - Pageable pageable = PageRequest.of(page, 10); + Pageable pageable = PageRequest.of(page, DEFAULT_PAGE_SIZE);src/main/java/com/example/dgu/returnwork/domain/region/controller/RegionApi.java (1)
83-91: searchKeyword 파라미터에 유효성 검증 추가를 고려하세요.searchKeyword 파라미터가 빈 문자열이나 공백만으로 구성되는 것을 방지하기 위해
@NotBlank검증을 추가하는 것이 좋습니다.다음 diff를 적용할 수 있습니다:
PageResponseDto<SearchRegionDto> searchRegion( @Parameter( description = "검색할 지역 키워드 (시/도, 시/군/구, 동/리 등)", example = "서울" ) + @NotBlank(message = "검색 키워드는 필수입니다") @RequestParam String searchKeyword, @RequestParam(defaultValue = "0") Integer page );src/main/java/com/example/dgu/returnwork/domain/region/Region.java (2)
8-37: 인스턴스 생성을 위한 빌더 또는 팩토리 메서드 추가 권장현재 엔티티에
protectedno-args 생성자만 존재하여 JPA 요구사항은 충족하지만, 테스트나 데이터 초기화 시 인스턴스를 생성할 명확한 방법이 없습니다. Lombok의@Builder나 정적 팩토리 메서드를 추가하는 것을 권장합니다.방법 1: Lombok @builder 추가 (권장)
@Entity @Table(name = "regions") @Getter +@Builder +@AllArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Region {방법 2: 정적 팩토리 메서드 추가
@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Region { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // ... 필드들 ... + + public static Region of(String fullAddress, String sido, String sigungu, + String dongLi, String sidoNormalized, String searchKeywords) { + Region region = new Region(); + region.fullAddress = fullAddress; + region.sido = sido; + region.sigungu = sigungu; + region.dongLi = dongLi; + region.sidoNormalized = sidoNormalized; + region.searchKeywords = searchKeywords; + return region; + } }
18-34: Bean Validation 애노테이션 추가 고려 (선택사항)현재 필드 검증이 JPA
@Column제약에만 의존하고 있습니다. Bean Validation 애노테이션(@NotNull,@Size등)을 추가하면 애플리케이션 레벨에서 더 일찍 검증할 수 있으며, 더 명확한 에러 메시지를 제공할 수 있습니다.+import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + @Entity @Table(name = "regions") @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Region { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @NotNull + @Size(max = 200) @Column(nullable = false, length = 200) private String fullAddress; + @Size(max = 50) @Column(length = 50) private String sido; // 나머지 필드들에도 유사하게 적용...
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
build.gradle(1 hunks)src/main/java/com/example/dgu/returnwork/domain/auth/dto/request/GoogleSignUpRequestDto.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/auth/dto/request/SignUpRequestDto.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/auth/service/AuthService.java(2 hunks)src/main/java/com/example/dgu/returnwork/domain/region/Region.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/region/controller/RegionApi.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/region/controller/RegionController.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/region/dto/response/SearchRegionDto.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/region/repository/RegionRepository.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/region/service/RegionQueryService.java(2 hunks)src/main/java/com/example/dgu/returnwork/domain/user/dto/request/UpdateUserInfoRequestDto.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/user/dto/response/GetUserInfoResponseDto.java(1 hunks)src/main/java/com/example/dgu/returnwork/domain/user/service/UserCommandService.java(1 hunks)src/main/java/com/example/dgu/returnwork/global/config/SecurityConfig.java(1 hunks)src/main/java/com/example/dgu/returnwork/global/dto/PageResponseDto.java(1 hunks)src/main/resources/application-local.yml(2 hunks)src/main/resources/db/migration/V1__create_tables.sql(1 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
src/main/resources/application-local.yml
[warning] 24-24: too many spaces before colon
(colons)
[warning] 26-26: too many spaces before colon
(colons)
🔇 Additional comments (16)
build.gradle (1)
65-67: LGTM!Flyway 의존성이 올바르게 추가되었습니다. Spring Boot의 dependency management가 버전을 관리하므로 별도의 버전 명시가 필요하지 않습니다.
src/main/resources/application-local.yml (1)
10-10: 로컬 환경에서validate모드 사용 확인 필요.
ddl-auto를update에서validate로 변경하셨습니다. 이는 Flyway로 스키마를 관리하는 프로덕션 환경에 적합하지만, 로컬 개발 환경에서는 엔티티 변경 시 수동으로 마이그레이션 스크립트를 작성해야 하는 번거로움이 있을 수 있습니다.로컬 개발 시 빠른 프로토타이핑이 필요한 경우
update모드 유지를 고려하거나, 팀 내에서 로컬 환경의 마이그레이션 관리 방침을 명확히 하시기 바랍니다.src/main/java/com/example/dgu/returnwork/global/config/SecurityConfig.java (1)
65-66: LGTM!지역 검색 API(
/api/regions)를 공개 엔드포인트로 추가한 것이 적절합니다. 회원가입 시 사용자가 인증 없이 지역을 조회할 수 있어야 하므로permitAll에 포함되는 것이 맞습니다.src/main/resources/db/migration/V1__create_tables.sql (1)
18-18:region_id NOT NULL제약 조건 검토 필요.
user테이블의region_id가NOT NULL로 정의되어 있습니다. 회원가입 시 반드시 지역을 선택해야 한다는 의미인데, 이것이 비즈니스 요구사항과 일치하는지 확인하시기 바랍니다.만약 선택적으로 지역을 입력받을 가능성이 있다면,
NULL을 허용하도록 수정해야 합니다.src/main/java/com/example/dgu/returnwork/domain/user/dto/response/GetUserInfoResponseDto.java (1)
39-39: LGTM!Region 엔티티의 확장된 주소 구조에 맞춰
getFullAddress()를 사용하도록 올바르게 변경되었습니다. 사용자에게 더 상세한 주소 정보를 제공할 수 있습니다.src/main/java/com/example/dgu/returnwork/domain/user/service/UserCommandService.java (1)
52-52: LGTM!
UpdateUserInfoRequestDto의 변경사항에 맞춰findRegionById를 사용하도록 올바르게 수정되었습니다. ID 기반 조회로 전환하여 더 명확하고 효율적인 지역 검색이 가능합니다.src/main/java/com/example/dgu/returnwork/domain/auth/service/AuthService.java (2)
57-57: LGTM!회원가입 시 지역 조회 로직이 ID 기반으로 올바르게 변경되었습니다.
SignUpRequestDto의 변경사항과 일치합니다.
117-117: LGTM!구글 회원가입 완료 시 지역 조회 로직이 ID 기반으로 올바르게 변경되었습니다.
GoogleSignUpRequestDto의 변경사항과 일치합니다.src/main/java/com/example/dgu/returnwork/domain/region/repository/RegionRepository.java (1)
13-14: LGTM!JPQL 쿼리가 올바르게 작성되었으며, LOWER 함수를 사용한 대소문자 구분 없는 검색과 LIKE를 통한 부분 검색이 적절하게 구현되었습니다.
src/main/java/com/example/dgu/returnwork/domain/region/dto/response/SearchRegionDto.java (1)
5-12: LGTM!간결하고 명확한 DTO 구현입니다. 정적 팩토리 메서드를 사용한 매핑도 적절합니다.
src/main/java/com/example/dgu/returnwork/domain/region/service/RegionQueryService.java (1)
21-24: LGTM!메서드 이름 변경과 ID 기반 조회 로직이 올바르게 구현되었습니다.
src/main/java/com/example/dgu/returnwork/global/dto/PageResponseDto.java (1)
7-26: LGTM!표준 페이지네이션 패턴을 따르는 깔끔한 구현입니다. Spring의 Page 객체를 올바르게 매핑하고 있으며, 필요한 모든 페이징 정보를 포함하고 있습니다.
src/main/java/com/example/dgu/returnwork/domain/region/controller/RegionApi.java (1)
20-82: LGTM!OpenAPI 문서화가 상세하고 명확하게 작성되었습니다. 성공/실패 케이스의 예제 응답이 모두 포함되어 있어 API 사용자에게 유용합니다.
src/main/java/com/example/dgu/returnwork/domain/region/Region.java (3)
21-28: 주소 필드 nullable 허용 여부 수동 검증 필요
sido,sigungu,dongLi필드가 모두 nullable로 설정되어 있습니다. 실제 DB 마이그레이션 파일과 도메인 로직에서 해당 컬럼의 null 허용 여부를 확인하고, 비즈니스 요구사항에 따라 최소sido필드가 필수인지 검증해주세요.
30-34: searchKeywords에 일반 B-tree 인덱스는 LIKE '%…%' 패턴에 적용되지 않습니다
현 쿼리(LOWER(r.searchKeywords) LIKE LOWER(CONCAT('%', :keyword, '%')))는 선행 와일드카드 사용으로 인해 B-tree 인덱스를 활용하지 못합니다. MySQL FULLTEXT 인덱스나 PostgreSQL GIN/pg_trgm 기반 full-text 검색 도입 혹은 와일드카드 위치 조정(예:%keyword→keyword%), 쿼리 패턴 변경을 검토하세요.Likely an incorrect or invalid review comment.
18-19:fullAddress필드 길이 검증 필요
fullAddress최대 길이 200자가 실제 생성되는 전체 주소(시도, 시군구, 동/리, 상세주소 포함)를 모두 담기에 충분한지, Region 생성 로직(엔티티 빌더 또는 서비스)에서 확인해주세요.
src/main/java/com/example/dgu/returnwork/domain/region/controller/RegionController.java
Outdated
Show resolved
Hide resolved
src/main/java/com/example/dgu/returnwork/domain/user/dto/request/UpdateUserInfoRequestDto.java
Show resolved
Hide resolved
Docstrings generation was requested by @oOccasio. * #64 (comment) The following files were modified: * `src/main/java/com/example/dgu/returnwork/domain/auth/service/AuthService.java` * `src/main/java/com/example/dgu/returnwork/domain/region/controller/RegionApi.java` * `src/main/java/com/example/dgu/returnwork/domain/region/controller/RegionController.java` * `src/main/java/com/example/dgu/returnwork/domain/region/dto/response/SearchRegionDto.java` * `src/main/java/com/example/dgu/returnwork/domain/region/repository/RegionRepository.java` * `src/main/java/com/example/dgu/returnwork/domain/region/service/RegionQueryService.java` * `src/main/java/com/example/dgu/returnwork/domain/user/dto/response/GetUserInfoResponseDto.java` * `src/main/java/com/example/dgu/returnwork/domain/user/service/UserCommandService.java` * `src/main/java/com/example/dgu/returnwork/global/config/SecurityConfig.java` * `src/main/java/com/example/dgu/returnwork/global/dto/PageResponseDto.java`
|
Note Generated docstrings for this pull request at #65 |
📝 요약
♻️ [refactor] - 상세 주소를 위해 Region 엔티티를 리팩토링한다
🔍 변경 사항
queryservice 개선
String 입력이 아닌 지역 id 입력으로 변경
📋 체크리스트
🔗 관련 이슈
Closes #61
Summary by CodeRabbit