Skip to content

판매자 회원가입 Service계층 테스트 코드 작성#173

Merged
1000hyehyang merged 20 commits intomainfrom
test/172-seller
Jul 13, 2025
Merged

판매자 회원가입 Service계층 테스트 코드 작성#173
1000hyehyang merged 20 commits intomainfrom
test/172-seller

Conversation

@1000hyehyang
Copy link
Member

@1000hyehyang 1000hyehyang commented Jul 12, 2025

⭐️ Issue Number

🚩 Summary

  • 판매자 회원가입 서비스 계층 수정 및 도메인 로직 강화
  • 포괄적인 테스트 코드 작성으로 코드 품질 및 안정성 확보
  • 정규화 처리 및 예외 처리 로직 개선

🛠️ Technical Concerns

1. 판매자 엔티티 도메인 로직 강화

  • 모든 필드에 trim() 정규화 적용으로 데이터 일관성 확보
  • 도메인 검증 로직을 SellerValidator로 분리하여 단일 책임 원칙 준수
  • BusinessException 기반 예외 처리로 통일성 확보

2. 판매자 회원가입 서비스 구현

  • 이메일, 사업자등록번호, 브랜드명 중복 체크 로직 구현
  • 비밀번호 암호화 처리 및 보안 강화
  • 정규화된 값으로 DB 저장하여 데이터 무결성 확보
  • 상세한 로깅 및 예외 처리로 디버깅 용이성 향상

3. 포괄적인 테스트 코드 작성

  • 정상/예외/경계조건/정규화/보안 테스트 시나리오 구현
  • SellerTestFixture로 테스트 데이터 중앙화하여 유지보수성 향상
  • Mockito를 활용한 정확한 Mock 설정으로 테스트 신뢰성 확보
  • 실제 서비스 로직과 일치하는 검증으로 테스트 정확성 보장

4. 코드 품질 개선

  • DRY 원칙 적용으로 코드 중복 제거
  • 가독성 향상을 위한 명확한 메서드명 및 주석 작성
  • 유지보수성 강화를 위한 모듈화 및 분리

🙂 To Reviewer

@songcw8
서비스 계층 테스트 코드만 확인해주시면 됩니다! 테스트 코드는 현재 모두 통과한 상태로 확인했습니다!

📋 To Do

Summary by CodeRabbit

  • 리팩터

    • 회원가입 입력값 검증, 정규화, 예외 처리를 모듈화하여 SellerService의 내부 로직을 개선하였습니다.
    • JPA 컬럼 길이 상수를 별도 상수로 분리하여 유지보수성을 높였습니다.
  • 테스트

    • 인증 및 소셜 로그인, 판매자 회원가입 등 주요 인증/회원가입 서비스에 대한 단위 및 통합 테스트가 대폭 추가되었습니다.
    • 테스트용 헬퍼 및 픽스처 클래스가 도입되어 다양한 예외, 경계, 성공 케이스를 체계적으로 검증합니다.
    • 테스트 코드의 중복 제거 및 가독성 향상을 위해 공통 베이스 클래스와 유틸리티 메서드가 도입되었습니다.
    • SellerService 회원가입 기능에 대한 상세한 시나리오별 테스트가 추가되어 정상, 중복, 경계, 예외, 동시성, 성능 등 다양한 상황을 검증합니다.
    • GoogleLoginService, KakaoLoginService, SocialLoginServiceFactory, SellerAuthService 등 소셜 및 판매자 인증 관련 테스트가 새로 추가되었습니다.
    • TokenValidator 테스트가 리팩터링되어 공통 베이스 클래스와 헬퍼 메서드를 활용하도록 개선되었습니다.
  • 스타일

    • 사용하지 않는 import 구문을 제거하여 코드 정리를 수행하였습니다.

- SellerAuthService 단위 테스트 추가 (로그인, 로그아웃, 예외 처리)
- GoogleLoginServiceTest Mockito strict stubbing 문제 해결
- KakaoLoginServiceTest RestClient 체인 모킹 누락 수정
- SocialLoginServiceFactoryTest 실제 enum 값(GOOGLE, KAKAO)만 사용하도록 수정
- TokenValidator 포괄적 테스트 추가 (토큰 검증, 사용자 정보 추출)
- AuthTestFixture 유틸리티 메서드 테스트 추가
- JsonProcessingException 예외 처리 개선
- 불필요한 stubbing 제거로 Mockito UnnecessaryStubbingException 해결
- RestClient 체인 호출 모킹 누락으로 인한 NPE 해결
- 예외 메시지 실제 서비스 코드와 일치하도록 조정
- AuthServiceTestBase에 Given-When-Then 패턴 헬퍼 메서드 구현
- AuthTestHelper 클래스 생성으로 공통 테스트 로직 중앙화
- TokenValidatorTest 리팩토링하여 새로운 헬퍼 메서드 활용
- Mockito lenient 사용으로 불필요한 stubbing 경고 해결
- 예외 메시지 일치성 문제 수정
- KakaoLoginServiceTest, GoogleLoginServiceTest, SellerAuthServiceTest를 실제 서비스 로직과 일치하도록 리팩토링
- RestClient 체인 모킹 헬퍼 및 공통 검증 메서드(AuthTestHelper) 추가
- processLogin 등 주요 메서드에서 findOrCreateMember, storeRefreshToken, generateAccessToken 등 호출 검증 강화
- 응답 DTO 필드 값 및 예외 상황 검증 보강
- 테스트 가독성 및 유지보수성 향상
- SellerTestFixture 클래스 생성
- 정상 판매자 데이터 생성 메서드 구현
- 예외 케이스 데이터 생성 메서드 구현 (중복 이메일, 사업자등록번호, 브랜드명)
- 삭제된 판매자 데이터 생성 메서드 구현
- 경계 조건 데이터 생성 메서드 구현 (이메일 대소문자, 공백, 최대/최소 길이)
- 특수 케이스 데이터 생성 메서드 구현 (특수문자, 한글)
- 리플렉션을 통한 테스트 유틸리티 메서드 구현

테스트 데이터 중앙화를 통해 객체 생성 방식 변경 시 한 곳에서만 수정 가능하며,
테스트 코드의 가독성과 일관성을 향상시킵니다.
- getSuperclass() 대신 명시적으로 BaseEntity.class 참조로 변경
- setBaseEntityField() 헬퍼 메서드 추가로 공통 로직 분리
- 향후 BaseEntity 구조 변경 시 테스트 안정성 향상
- 리플렉션 코드의 의존성 명확화 및 유지보수성 강화
- givenDeletedSellerExists 메서드에서 findActiveSeller 반환값을 Optional.empty()로 수정
- 삭제된 판매자는 활성 상태가 아니므로 findActiveSeller에서 조회되지 않아야 함
- 실제 비즈니스 로직과 테스트 시나리오의 일치성 향상
- thenRefreshTokenShouldBeStored 파라미터 순서를 실제 메서드와 일치하도록 변경
- 테스트 헬퍼 메서드의 일관성 향상
- 판매자 엔티티 도메인 로직 강화
  - 모든 필드에 trim() 정규화 적용
  - 도메인 검증 로직을 SellerValidator로 분리
  - BusinessException 기반 예외 처리 통일

- 판매자 회원가입 서비스 구현
  - 이메일, 사업자등록번호, 브랜드명 중복 체크
  - 비밀번호 암호화 처리
  - 정규화된 값으로 DB 저장
  - 상세한 로깅 및 예외 처리

- 포괄적인 테스트 코드 작성
  - 정상/예외/경계조건/정규화/보안 테스트
  - SellerTestFixture로 테스트 데이터 중앙화
  - Mockito를 활용한 정확한 Mock 설정
  - 실제 서비스 로직과 일치하는 검증

- 코드 품질 개선
  - DRY 원칙 적용
  - 가독성 향상
  - 유지보수성 강화
@1000hyehyang 1000hyehyang requested a review from songcw8 July 12, 2025 20:12
@1000hyehyang 1000hyehyang added 🔥 BE 백엔드 이슈 🛠️ Refactor 리팩터링 이슈 ✅ Test 테스트 이슈 labels Jul 12, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 12, 2025

Warning

Rate limit exceeded

@1000hyehyang has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 53 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between fdd3fe6 and 42be4b0.

📒 Files selected for processing (1)
  • src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1 hunks)

"""

Walkthrough

이번 변경 사항은 판매자 회원가입 서비스의 입력 검증, 정규화, 예외 처리 로직을 모듈화하고, JPA 엔티티의 컬럼 길이 상수를 별도 상수 클래스로 이관하여 유지보수성을 높였습니다. 또한, 판매자 회원가입 및 인증 관련 테스트 코드와 테스트 픽스처, 다양한 예외 및 경계 조건 테스트가 대거 추가되었습니다.

Changes

파일/경로 요약 변경 내용 요약
src/main/java/com/ururulab/ururu/seller/domain/entity/Seller.java JPA 컬럼 길이 하드코딩 값을 SellerConstants 상수로 대체
src/main/java/com/ururulab/ururu/seller/service/SellerService.java 회원가입 내부 로직 모듈화(정규화, 검증, 예외처리), 예외 코드 통일, 중복체크/정규화 메서드 분리
src/test/java/com/ururulab/ururu/auth/AuthTestFixtureTest.java 불필요한 import 제거
src/test/java/com/ururulab/ururu/auth/AuthTestHelper.java 인증 관련 테스트 유틸리티 클래스 신설, 토큰/예외/Mock/성능 검증 등 다양한 static 메서드 제공
src/test/java/com/ururulab/ururu/auth/service/AuthServiceTestBase.java 인증 테스트 베이스 클래스에 Given/When/Then 헬퍼 메서드 대거 추가, Mock/검증/통합 시나리오 지원
src/test/java/com/ururulab/ururu/auth/service/SellerAuthServiceTest.java 판매자 인증 서비스 단위 테스트 신설: 로그인/로그아웃/예외처리 시나리오 검증
src/test/java/com/ururulab/ururu/auth/service/SocialLoginServiceFactoryTest.java 소셜 로그인 서비스 팩토리 동작 검증 테스트 신설(정상/예외 케이스)
src/test/java/com/ururulab/ururu/auth/service/TokenValidatorTest.java 테스트 베이스 상속, 헬퍼 메서드 활용으로 테스트 코드 리팩토링 및 간결화
src/test/java/com/ururulab/ururu/auth/service/social/GoogleLoginServiceTest.java 구글 소셜 로그인 서비스 단위 테스트 신설: 인증 URL/토큰/회원정보/로그인/예외처리 등
src/test/java/com/ururulab/ururu/auth/service/social/KakaoLoginServiceTest.java 카카오 소셜 로그인 서비스 단위 테스트 신설: 정상/예외 플로우 검증
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java 판매자 회원가입 서비스 통합 테스트 신설: 정상, 예외, 경계, 성능, 동시성 등 다양한 케이스 검증
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java 판매자 테스트 픽스처 클래스 신설: 다양한 Seller/SignupRequest 생성 및 유틸리티 제공

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant SellerService
    participant SellerRepository
    participant PasswordEncoder

    Client->>SellerService: signup(request)
    SellerService->>SellerService: normalizeEmail(request.email)
    SellerService->>SellerService: encodePassword(request.password)
    SellerService->>SellerService: validateSignupRequest(request, normalizedEmail)
    SellerService->>SellerRepository: existsByEmail/BusinessNumber/Name
    SellerService->>SellerService: createSellerEntity(request, normalizedEmail, encodedPassword)
    SellerService->>SellerRepository: save(seller)
    SellerService-->>Client: SellerResponse
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers

  • songcw8

Poem

🐰
테스트 토끼가 껑충 뛰어
회원가입도 인증도 꼼꼼히 살펴요!
상수로 길이 딱 맞추고
예외도 중복도 놓치지 않죠.
픽스처와 헬퍼로 든든한 지원군,
오늘도 토끼는 품질을 지켜요!
🥕
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (11)
src/test/java/com/ururulab/ururu/auth/service/social/KakaoLoginServiceTest.java (1)

56-80: RestClient 체이닝 모킹 복잡도 개선 제안

현재 RestClient 체이닝 모킹이 복잡합니다. AuthTestHelper.setupRestClientChain() 메서드를 활용하면 중복 코드를 줄이고 가독성을 향상시킬 수 있습니다.

@BeforeEach
@SuppressWarnings("unchecked")
void setUp() {
    MockitoAnnotations.openMocks(this);
-   // RestClient 체이닝 모킹
-   when(socialLoginRestClient.post()).thenReturn(requestBodyUriSpec);
-   when(socialLoginRestClient.get()).thenReturn(requestHeadersUriSpec);
-   when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec);
-   when(requestBodyUriSpec.contentType(any(MediaType.class))).thenReturn(requestBodyUriSpec);
-   when(requestBodyUriSpec.body(anyString())).thenReturn(requestBodyUriSpec);
-   when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec);
-   when(requestHeadersUriSpec.uri(anyString())).thenReturn(requestHeadersUriSpec);
-   when(requestHeadersUriSpec.header(anyString(), anyString())).thenReturn(requestHeadersUriSpec);
-   when(requestHeadersUriSpec.retrieve()).thenReturn(responseSpec);
-   when(responseSpec.onStatus(any(), any())).thenReturn(responseSpec);
+   AuthTestHelper.setupRestClientChain(socialLoginRestClient, "token_uri", "memberInfoUri");
src/test/java/com/ururulab/ururu/auth/service/social/GoogleLoginServiceTest.java (2)

122-141: RestClient 모킹 설정의 중복 제거 필요

RestClient 체이닝 모킹 코드가 여러 테스트 메서드에서 반복되고 있습니다. 테스트 가독성과 유지보수성 향상을 위해 헬퍼 메서드로 추출하는 것을 고려해보세요.

+    private RestClient.ResponseSpec setupTokenExchangeMock(String tokenUri, String requestBody, String response) {
+        RestClient.RequestBodyUriSpec requestBodyUriSpec = mock(RestClient.RequestBodyUriSpec.class);
+        RestClient.RequestBodySpec requestBodySpec = mock(RestClient.RequestBodySpec.class);
+        RestClient.ResponseSpec responseSpec = mock(RestClient.ResponseSpec.class);
+        
+        when(restClient.post()).thenReturn(requestBodyUriSpec);
+        when(requestBodyUriSpec.uri(tokenUri)).thenReturn(requestBodySpec);
+        when(requestBodySpec.contentType(MediaType.APPLICATION_FORM_URLENCODED)).thenReturn(requestBodySpec);
+        when(requestBodySpec.body(requestBody)).thenReturn(requestBodySpec);
+        when(requestBodySpec.retrieve()).thenReturn(responseSpec);
+        when(responseSpec.onStatus(any(), any())).thenReturn(responseSpec);
+        when(responseSpec.body(String.class)).thenReturn(response);
+        
+        return responseSpec;
+    }

그런 다음 각 테스트에서:

-            RestClient.RequestBodyUriSpec requestBodyUriSpec = mock(RestClient.RequestBodyUriSpec.class);
-            RestClient.RequestBodySpec requestBodySpec = mock(RestClient.RequestBodySpec.class);
-            RestClient.ResponseSpec responseSpec = mock(RestClient.ResponseSpec.class);
-            
-            // ... 여러 줄의 when() 설정 ...
+            String requestBody = googleOAuthProperties.buildTokenRequestBody(authCode);
+            setupTokenExchangeMock(tokenUri, requestBody, mockResponse);

Also applies to: 154-189, 204-218, 232-250


333-431: 긴 테스트 메서드의 가독성 개선 필요

processLogin_success 테스트가 100줄이 넘어 가독성과 유지보수성이 떨어집니다. 모킹 설정을 별도의 헬퍼 메서드로 분리하는 것을 고려해보세요.

+    private void setupTokenExchangeForProcessLogin(String authCode, String tokenUri, String expectedAccessToken) {
+        // Token exchange mocking 로직을 여기로 이동
+    }
+    
+    private void setupMemberInfoRetrievalForProcessLogin(String memberInfoUri, String memberInfoResponse) {
+        // Member info mocking 로직을 여기로 이동
+    }
+    
+    private void setupMemberServiceForProcessLogin(Member mockMember) {
+        // Member service mocking 로직을 여기로 이동
+    }
+    
+    private void setupJwtGenerationForProcessLogin() {
+        // JWT token generation mocking 로직을 여기로 이동
+    }

이렇게 하면 테스트 메서드가 더 간결하고 읽기 쉬워집니다.

src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1)

502-502: 성능 테스트의 임계값이 너무 관대함

Mock을 사용하는 단위 테스트에서 1초는 너무 긴 시간입니다. 일반적으로 서비스 레이어 단위 테스트는 100ms 이내에 완료되어야 합니다.

-            assertThat(endTime - startTime).isLessThan(1000); // 1초 이내 처리
+            assertThat(endTime - startTime).isLessThan(100); // 100ms 이내 처리
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (2)

70-70: 반복되는 테스트 데이터를 상수로 추출

여러 메서드에서 동일한 값들이 반복 사용되고 있습니다. 유지보수성 향상을 위해 상수로 추출하는 것을 고려해보세요.

 public class SellerTestFixture {
 
+    // 공통 테스트 데이터 상수
+    private static final String DEFAULT_PASSWORD = "Password123!";
+    private static final String DEFAULT_BUSINESS_NUMBER = "1234567890";
+    private static final String DEFAULT_PHONE = "01012345678";
+    private static final String DEFAULT_ADDRESS1 = "서울시 강남구 테헤란로 123";
+    private static final String DEFAULT_ADDRESS2 = "456호";
+    private static final String DEFAULT_MAIL_ORDER_NUMBER = "2024-서울강남-1234";
+
     // === 정상 판매자 데이터 ===

그런 다음 각 메서드에서:

-                "Password123!",
-                "01012345678",
+                DEFAULT_PASSWORD,
+                DEFAULT_PHONE,

Also applies to: 89-89, 108-108, 129-129, 148-148, 190-190, 208-208, 227-227, 246-246, 268-268, 286-286, 305-305, 325-325, 343-343


362-364: 리플렉션 예외 처리 시 더 구체적인 에러 메시지 제공

리플렉션 실패 시 어떤 필드에서 문제가 발생했는지 더 명확한 정보를 제공하면 디버깅이 쉬워집니다.

         } catch (Exception e) {
-            throw new RuntimeException("Failed to set seller id for test", e);
+            throw new RuntimeException(String.format("Failed to set seller id '%d' for test: %s", id, e.getMessage()), e);
         }

다른 메서드들도 동일하게:

-            throw new RuntimeException("Failed to set seller timestamps for test", e);
+            throw new RuntimeException(String.format("Failed to set seller timestamps (createdAt=%s, updatedAt=%s) for test: %s", 
+                    createdAt, updatedAt, e.getMessage()), e);

Also applies to: 380-382, 393-395, 407-409

src/test/java/com/ururulab/ururu/auth/AuthTestHelper.java (1)

34-379: 큰 헬퍼 클래스를 책임별로 분리 고려

379줄의 긴 클래스가 다양한 책임을 가지고 있습니다. 응집도를 높이고 유지보수성을 개선하기 위해 책임별로 분리하는 것을 고려해보세요.

다음과 같이 분리할 수 있습니다:

  • TokenValidationTestHelper: 토큰 검증 관련 메서드 (40-107줄)
  • ExceptionVerificationTestHelper: 예외 검증 메서드 (108-145줄)
  • MockSetupTestHelper: Mock 설정 메서드 (147-176줄)
  • PerformanceTestHelper: 성능 테스트 메서드 (292-310줄)
  • StringMaskingTestHelper: 문자열 마스킹 검증 메서드 (312-340줄)

예시:

public final class TokenValidationTestHelper {
    private TokenValidationTestHelper() {}
    
    public static void verifyTokenValidation(...) { ... }
    public static void verifyRefreshTokenValidation(...) { ... }
    // 기타 토큰 관련 메서드들
}

public final class AuthTestHelper {
    // 통합 검증 메서드들과 자주 사용되는 핵심 메서드만 유지
}
src/main/java/com/ururulab/ururu/seller/service/SellerService.java (2)

76-81: 중복된 정규화 로직을 공통 메서드로 추출

normalizeEmail, normalizeBusinessNumber, normalizeName 메서드들이 유사한 패턴을 가지고 있습니다. DRY 원칙에 따라 공통 로직을 추출하는 것을 고려해보세요.

+    /**
+     * 필수 필드 정규화 및 검증
+     */
+    private String normalizeRequiredField(final String field, final String fieldName) {
+        if (field == null || field.isBlank()) {
+            throw new BusinessException(ErrorCode.INVALID_ARGUMENT, fieldName + "은(는) 필수입니다.");
+        }
+        return field.trim();
+    }
+
     /**
      * 이메일 정규화
      */
     private String normalizeEmail(final String email) {
-        if (email == null || email.isBlank()) {
-            throw new BusinessException(ErrorCode.INVALID_ARGUMENT, "이메일은 필수입니다.");
-        }
-        return email.toLowerCase().trim();
+        return normalizeRequiredField(email, "이메일").toLowerCase();
     }
     
     /**
      * 사업자등록번호 정규화
      */
     private String normalizeBusinessNumber(final String businessNumber) {
-        if (businessNumber == null || businessNumber.isBlank()) {
-            throw new BusinessException(ErrorCode.INVALID_ARGUMENT, "사업자등록번호는 필수입니다.");
-        }
-        return businessNumber.trim();
+        return normalizeRequiredField(businessNumber, "사업자등록번호");
     }
     
     /**
      * 브랜드명 정규화
      */
     private String normalizeName(final String name) {
-        if (name == null || name.isBlank()) {
-            throw new BusinessException(ErrorCode.INVALID_ARGUMENT, "브랜드명은 필수입니다.");
-        }
-        return name.trim();
+        return normalizeRequiredField(name, "브랜드명");
     }

Also applies to: 179-184, 189-194


136-174: 필수 필드 검증의 중복 제거 필요

validateRequiredFields 메서드의 검증이 각 정규화 메서드(normalizeEmail, normalizeBusinessNumber, normalizeName)에서도 수행되고 있어 중복됩니다.

정규화 메서드들이 이미 필수 필드 검증을 수행하므로, validateRequiredFields 메서드를 제거하거나 간소화할 수 있습니다:

     private void validateSignupRequest(final SellerSignupRequest request, final String normalizedEmail) {
-        // 필수 필드 검증
-        validateRequiredFields(request);
-        
         // 이메일 중복 체크
         if (!sellerRepository.isEmailAvailable(normalizedEmail)) {
             log.warn("이메일 중복: {}", MaskingUtils.maskEmail(normalizedEmail));
             throw new BusinessException(ErrorCode.DUPLICATE_EMAIL);
         }

         // 사업자등록번호 정규화 후 중복 체크
+        // normalizeBusinessNumber 내부에서 필수 체크 수행
         final String normalizedBusinessNumber = normalizeBusinessNumber(request.businessNumber());
         if (!sellerRepository.isBusinessNumberAvailable(normalizedBusinessNumber)) {
             log.warn("사업자등록번호 중복: {}", MaskingUtils.maskBusinessNumber(normalizedBusinessNumber));
             throw new BusinessException(ErrorCode.DUPLICATE_BUSINESS_NUMBER);
         }

         // 브랜드명 정규화 후 중복 체크
+        // normalizeName 내부에서 필수 체크 수행
         final String normalizedName = normalizeName(request.name());
         if (!sellerRepository.isNameAvailable(normalizedName)) {
             log.warn("브랜드명 중복: {}", normalizedName);
             throw new BusinessException(ErrorCode.DUPLICATE_BRAND_NAME);
         }
     }
-
-    /**
-     * 필수 필드 검증
-     */
-    private void validateRequiredFields(final SellerSignupRequest request) {
-        if (request.name() == null || request.name().isBlank()) {
-            throw new BusinessException(ErrorCode.INVALID_ARGUMENT, "브랜드명은 필수입니다.");
-        }
-        if (request.businessNumber() == null || request.businessNumber().isBlank()) {
-            throw new BusinessException(ErrorCode.INVALID_ARGUMENT, "사업자등록번호는 필수입니다.");
-        }
-        if (request.password() == null || request.password().isBlank()) {
-            throw new BusinessException(ErrorCode.INVALID_ARGUMENT, "비밀번호는 필수입니다.");
-        }
-    }
src/test/java/com/ururulab/ururu/auth/service/AuthServiceTestBase.java (2)

280-311: 중복된 Refresh Token 검증 메서드 통합 검토

verifyRefreshTokenValidationverifyCompleteRefreshTokenValidation 메서드가 동일한 로직을 수행하고 있습니다. 하나로 통합하거나 명확한 차이점을 두는 것을 고려해보세요.

두 메서드를 하나로 통합:

-    protected void verifyRefreshTokenValidation(TokenValidator validator, String token, Long expectedUserId, String expectedUserType) {
-        // Given
-        String tokenId = jwtTokenProvider.getTokenId(token);
-        givenTokenIsNotBlacklisted(tokenId);
-
-        // When
-        TokenValidator.TokenValidationResult result = whenValidateRefreshToken(validator, token);
-
-        // Then
-        thenTokenValidationShouldSucceed(result, expectedUserId, expectedUserType);
-        thenTokenShouldBeValid(token);
-        thenShouldBeRefreshToken(token);
-        thenTokenShouldNotBeExpired(token);
-    }
-
     /**
      * 전체 Refresh Token 검증 플로우를 테스트합니다.
      */
     protected void verifyCompleteRefreshTokenValidation(TokenValidator validator, String token, Long expectedUserId, String expectedUserType) {

35-355: 테스트 기반 클래스의 모듈화 고려

현재 350줄이 넘는 대규모 테스트 기반 클래스입니다. 향후 유지보수성을 위해 기능별로 분리된 헬퍼 클래스들로 모듈화하는 것을 고려해보세요.

예를 들어:

  • AuthTestDataHelper: Given 메서드들
  • AuthTestActionHelper: When 메서드들
  • AuthTestAssertionHelper: Then 메서드들
  • AuthTestIntegrationHelper: 통합 헬퍼 메서드들

이렇게 분리하면 각 헬퍼의 책임이 명확해지고 테스트 코드의 재사용성이 향상됩니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a366dd and 29435c3.

📒 Files selected for processing (12)
  • src/main/java/com/ururulab/ururu/seller/domain/entity/Seller.java (1 hunks)
  • src/main/java/com/ururulab/ururu/seller/service/SellerService.java (4 hunks)
  • src/test/java/com/ururulab/ururu/auth/AuthTestFixtureTest.java (0 hunks)
  • src/test/java/com/ururulab/ururu/auth/AuthTestHelper.java (1 hunks)
  • src/test/java/com/ururulab/ururu/auth/service/AuthServiceTestBase.java (2 hunks)
  • src/test/java/com/ururulab/ururu/auth/service/SellerAuthServiceTest.java (1 hunks)
  • src/test/java/com/ururulab/ururu/auth/service/SocialLoginServiceFactoryTest.java (1 hunks)
  • src/test/java/com/ururulab/ururu/auth/service/TokenValidatorTest.java (16 hunks)
  • src/test/java/com/ururulab/ururu/auth/service/social/GoogleLoginServiceTest.java (1 hunks)
  • src/test/java/com/ururulab/ururu/auth/service/social/KakaoLoginServiceTest.java (1 hunks)
  • src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1 hunks)
  • src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1 hunks)
💤 Files with no reviewable changes (1)
  • src/test/java/com/ururulab/ururu/auth/AuthTestFixtureTest.java
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: songcw8
PR: UruruLab/Ururu-Backend#149
File: src/main/java/com/ururulab/ururu/global/config/SecurityConfig.java:49-50
Timestamp: 2025-07-11T06:26:59.125Z
Learning: 사용자 songcw8은 보안 관련 피드백(임시 permitAll() 설정 제거 계획 수립)에 대해 적극적으로 대응하고 반영하는 자세를 보이며, 개발 편의성과 보안성 사이의 균형을 이해하고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:213-241
Timestamp: 2025-06-26T16:45:33.604Z
Learning: Ururu-Backend 프로젝트에서 CartService의 validatePurchaseLimit 메서드의 성능 최적화 (CQRS 패턴, UserPurchaseSummary 테이블 등)는 기능 구현 완료 후 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#43
File: src/main/java/com/ururulab/ururu/auth/service/social/KakaoLoginService.java:108-139
Timestamp: 2025-06-24T06:08:49.466Z
Learning: 사용자 23MinL은 KakaoLoginService에서 외부 API 호출(getAccessToken, getMemberInfo)을 트랜잭션 범위에서 분리하여 데이터베이스 연결을 최적화하는 제안에 동의하고 적용하기로 했습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#109
File: src/main/java/com/ururulab/ururu/payment/service/PaymentService.java:157-181
Timestamp: 2025-07-03T04:34:42.502Z
Learning: Ururu-Backend 프로젝트의 PaymentService에서 결제 승인 시 동시성 제어를 위해 Payment 엔티티에 @Version 필드를 추가하여 낙관적 락을 적용하기로 결정했습니다. 이는 기존의 Redis 분산 락과 JPA @Version 낙관적 락을 통한 2단계 보호 메커니즘과 일관성을 유지하는 접근입니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/domain/repository/CartRepository.java:14-27
Timestamp: 2025-06-26T16:47:30.315Z
Learning: Ururu-Backend 프로젝트에서 CartRepository의 복잡한 페치 조인 쿼리(5개의 LEFT JOIN FETCH) 성능 최적화는 기능 구현 완료 후 CQRS 패턴이나 UserPurchaseSummary 테이블 도입을 통해 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 1억원, 수량이 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#38
File: src/main/java/com/ururulab/ururu/order/domain/entity/Order.java:67-96
Timestamp: 2025-06-23T03:48:45.602Z
Learning: Order domain entity에서 필수 필드 검증은 DTO validation으로 처리할 예정입니다. 도메인 엔티티 레벨에서는 비즈니스 로직에 집중하고 입력 검증은 DTO 레이어에서 담당하는 아키텍처 접근법을 사용합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:115-133
Timestamp: 2025-06-26T16:29:03.796Z
Learning: Ururu-Backend 프로젝트에서 CartItem.decreaseQuantity() 메서드는 내부적으로 수량 검증 로직을 구현하고 있으며, 엔티티 레벨에서 도메인 규칙을 관리하는 DDD 원칙을 따라 서비스 레이어에서의 중복 검증을 피하고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/domain/entity/ReviewImage.java:38-39
Timestamp: 2025-06-20T19:50:35.318Z
Learning: Joowon-Seo 프로젝트에서 JPA 엔티티 필드 타입 선택 시 다음 가이드라인을 선호: 1) 필수 불린 플래그는 boolean + 명시적 초기화 사용, 2) 팀 일관성을 위해 원시타입과 래퍼타입 사용 규칙 정립 필요, 3) 데이터베이스 제약조건과 JPA 엔티티 필드 타입 일치시키기 중요
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 PaymentPolicy.MAX_AMOUNT = 100_000_000 (1억원), 수량이 OrderValidationConstants.QUANTITY_MAX = 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
src/main/java/com/ururulab/ururu/seller/domain/entity/Seller.java (1)
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/domain/entity/ReviewImage.java:38-39
Timestamp: 2025-06-20T19:50:35.318Z
Learning: Joowon-Seo 프로젝트에서 JPA 엔티티 필드 타입 선택 시 다음 가이드라인을 선호: 1) 필수 불린 플래그는 boolean + 명시적 초기화 사용, 2) 팀 일관성을 위해 원시타입과 래퍼타입 사용 규칙 정립 필요, 3) 데이터베이스 제약조건과 JPA 엔티티 필드 타입 일치시키기 중요
src/test/java/com/ururulab/ururu/auth/service/TokenValidatorTest.java (2)
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#68
File: src/main/java/com/ururulab/ururu/auth/controller/JwtRefreshController.java:55-62
Timestamp: 2025-06-26T05:55:47.583Z
Learning: 사용자 23MinL은 JWT 컨트롤러에서 예외 처리 시 JwtException은 401 상태와 log.warn(), RedisConnectionFailureException은 500 상태와 log.error()를 사용하는 패턴을 선호한다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#23
File: src/main/java/com/ururulab/ururu/global/auth/jwt/JwtProperties.java:11-22
Timestamp: 2025-06-21T00:48:30.080Z
Learning: 개발자 23MinL은 JWT 관련 보안 개선사항(불변성, 검증 로직 등)을 실제 토큰 기능 구현 시점에 적용하는 것을 선호한다고 명시했다.
src/test/java/com/ururulab/ururu/auth/service/social/KakaoLoginServiceTest.java (3)
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#43
File: src/main/java/com/ururulab/ururu/auth/service/social/KakaoLoginService.java:108-139
Timestamp: 2025-06-24T06:08:49.466Z
Learning: 사용자 23MinL은 KakaoLoginService에서 외부 API 호출(getAccessToken, getMemberInfo)을 트랜잭션 범위에서 분리하여 데이터베이스 연결을 최적화하는 제안에 동의하고 적용하기로 했습니다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#68
File: src/main/java/com/ururulab/ururu/auth/controller/JwtRefreshController.java:55-62
Timestamp: 2025-06-26T05:55:47.583Z
Learning: 사용자 23MinL은 JWT 컨트롤러에서 예외 처리 시 JwtException은 401 상태와 log.warn(), RedisConnectionFailureException은 500 상태와 log.error()를 사용하는 패턴을 선호한다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/controller/ReviewController.java:40-46
Timestamp: 2025-06-22T05:13:51.327Z
Learning: ReviewController에서 하드코딩된 Member 인스턴스 사용은 JWT 인증 구현 전 임시 코드입니다. 현재는 개발 초기 단계로 비즈니스 로직 구현에 집중하고 있으며, 인증/권한 부여는 추후 JWT 구현 시 추가될 예정입니다.
src/test/java/com/ururulab/ururu/auth/service/SellerAuthServiceTest.java (1)
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (3)
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: 1000hyehyang
PR: UruruLab/Ururu-Backend#169
File: src/test/java/com/ururulab/ururu/auth/service/AuthServiceTestBase.java:315-320
Timestamp: 2025-07-12T18:02:29.718Z
Learning: 테스트 메서드의 파라미터 순서는 실제 호출하는 메서드의 시그니처와 일치해야 합니다. 테스트 클래스 내에서 인위적인 일관성보다는 실제 메서드 호출과의 일치성을 우선시해야 합니다.
src/main/java/com/ururulab/ururu/seller/service/SellerService.java (2)
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#58
File: src/main/java/com/ururulab/ururu/order/domain/entity/OrderHistory.java:29-30
Timestamp: 2025-06-25T07:18:38.919Z
Learning: In the Ururu-Backend Java project, the team prefers to handle validation logic in domain entity static factory methods rather than using Bean Validation annotations, to maintain domain consistency and follow domain-driven design principles.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#38
File: src/main/java/com/ururulab/ururu/order/domain/entity/Order.java:67-96
Timestamp: 2025-06-23T03:48:45.602Z
Learning: Order domain entity에서 필수 필드 검증은 DTO validation으로 처리할 예정입니다. 도메인 엔티티 레벨에서는 비즈니스 로직에 집중하고 입력 검증은 DTO 레이어에서 담당하는 아키텍처 접근법을 사용합니다.
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1)
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
src/test/java/com/ururulab/ururu/auth/AuthTestHelper.java (5)
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/controller/ReviewController.java:28-38
Timestamp: 2025-06-21T10:52:58.538Z
Learning: ReviewController에서 하드코딩된 정적 Member 인스턴스는 JWT 인증 구현 전 임시 구현입니다. JWT 인증이 구현되면 실제 인증된 사용자 정보로 대체될 예정입니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/controller/ReviewController.java:40-46
Timestamp: 2025-06-22T05:13:51.327Z
Learning: ReviewController에서 하드코딩된 Member 인스턴스 사용은 JWT 인증 구현 전 임시 코드입니다. 현재는 개발 초기 단계로 비즈니스 로직 구현에 집중하고 있으며, 인증/권한 부여는 추후 JWT 구현 시 추가될 예정입니다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#113
File: src/main/java/com/ururulab/ururu/global/config/SecurityConfig.java:47-47
Timestamp: 2025-07-03T02:43:54.487Z
Learning: 사용자 23MinL은 보안 설정에서 SecurityConfig와 JwtAuthenticationFilter 간의 일관성을 중시하며, 헬스체크 엔드포인트 경로 통일 등 관련 컴포넌트 간의 설정 일관성 유지를 선호합니다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#68
File: src/main/java/com/ururulab/ururu/auth/controller/JwtRefreshController.java:55-62
Timestamp: 2025-06-26T05:55:47.583Z
Learning: 사용자 23MinL은 JWT 컨트롤러에서 예외 처리 시 JwtException은 401 상태와 log.warn(), RedisConnectionFailureException은 500 상태와 log.error()를 사용하는 패턴을 선호한다.
src/test/java/com/ururulab/ururu/auth/service/AuthServiceTestBase.java (4)
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/controller/ReviewController.java:40-46
Timestamp: 2025-06-22T05:13:51.327Z
Learning: ReviewController에서 하드코딩된 Member 인스턴스 사용은 JWT 인증 구현 전 임시 코드입니다. 현재는 개발 초기 단계로 비즈니스 로직 구현에 집중하고 있으며, 인증/권한 부여는 추후 JWT 구현 시 추가될 예정입니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/controller/ReviewController.java:28-38
Timestamp: 2025-06-21T10:52:58.538Z
Learning: ReviewController에서 하드코딩된 정적 Member 인스턴스는 JWT 인증 구현 전 임시 구현입니다. JWT 인증이 구현되면 실제 인증된 사용자 정보로 대체될 예정입니다.
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#68
File: src/main/java/com/ururulab/ururu/auth/controller/JwtRefreshController.java:55-62
Timestamp: 2025-06-26T05:55:47.583Z
Learning: 사용자 23MinL은 JWT 컨트롤러에서 예외 처리 시 JwtException은 401 상태와 log.warn(), RedisConnectionFailureException은 500 상태와 log.error()를 사용하는 패턴을 선호한다.
🧬 Code Graph Analysis (3)
src/test/java/com/ururulab/ururu/auth/service/TokenValidatorTest.java (1)
src/test/java/com/ururulab/ururu/auth/AuthTestFixture.java (1)
  • AuthTestFixture (27-387)
src/test/java/com/ururulab/ururu/auth/service/social/KakaoLoginServiceTest.java (2)
src/test/java/com/ururulab/ururu/auth/AuthTestHelper.java (1)
  • AuthTestHelper (34-379)
src/test/java/com/ururulab/ururu/auth/service/SocialLoginServiceFactoryTest.java (1)
  • DisplayName (16-64)
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1)
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1)
  • SellerTestFixture (16-411)
🔇 Additional comments (14)
src/main/java/com/ururulab/ururu/seller/domain/entity/Seller.java (1)

40-53: 상수 추출로 유지보수성 향상 우수

하드코딩된 컬럼 길이를 SellerConstants로 추출한 리팩토링이 잘 되었습니다. DRY 원칙을 준수하고 중앙집중식 상수 관리로 유지보수성이 크게 향상되었습니다. 주석으로 고정 길이 사용 이유를 명확히 설명한 점도 좋습니다.

src/test/java/com/ururulab/ururu/auth/service/SocialLoginServiceFactoryTest.java (1)

16-64: 포괄적인 팩토리 패턴 테스트 구현 우수

SocialLoginServiceFactory의 모든 주요 시나리오를 잘 다루고 있습니다:

  • 정상 케이스: Google/Kakao 서비스 반환
  • 예외 케이스: null provider, 미지원 provider
  • 적절한 모킹과 예외 검증 사용

테스트 구조가 명확하고 예외 처리 검증이 정확합니다.

src/test/java/com/ururulab/ururu/auth/service/social/KakaoLoginServiceTest.java (2)

82-151: 카카오 로그인 성공 시나리오 테스트 우수

정상 로그인 플로우를 매우 상세하게 검증하고 있습니다:

  • JSON 파싱 과정의 모든 단계 모킹
  • 서비스 상호작용 검증
  • JWT 토큰 생성 및 저장 확인
  • 응답 데이터 정확성 검증

실제 구현과 일치하는 검증 로직이 잘 구현되었습니다.


153-191: 예외 시나리오 테스트 포괄적 구현

필수 매개변수 누락 및 JSON 파싱 실패 등 주요 예외 상황을 모두 다루고 있어 견고한 테스트입니다. 각 예외에 대한 적절한 에러 메시지와 예외 타입 검증이 잘 되어 있습니다.

src/test/java/com/ururulab/ururu/auth/service/SellerAuthServiceTest.java (3)

50-94: 판매자 로그인 성공 시나리오 테스트 우수

로그인 플로우의 모든 단계를 체계적으로 검증하고 있습니다:

  • 판매자 조회 및 비밀번호 검증
  • 계정 상태 확인
  • JWT 토큰 생성 및 저장
  • 응답 데이터 정확성 검증

모킹과 검증 로직이 실제 서비스 구현과 정확히 일치합니다.


96-144: 인증 실패 시나리오 테스트 포괄적 구현

비밀번호 불일치, 삭제된 계정, 존재하지 않는 판매자 등 주요 인증 실패 케이스를 모두 다루고 있습니다. 각 시나리오에 대한 적절한 ErrorCode 검증이 잘 구현되었습니다.


146-170: 로그아웃 기능 테스트 구현 우수

logout()logoutWithToken() 두 가지 로그아웃 방식을 모두 테스트하여 완전한 커버리지를 제공합니다. JwtRefreshService와의 상호작용 검증이 적절합니다.

src/test/java/com/ururulab/ururu/auth/service/TokenValidatorTest.java (4)

25-36: AuthServiceTestBase 상속으로 코드 재사용성 향상

AuthServiceTestBase를 상속하여 공통 설정과 헬퍼 메서드를 재사용하는 리팩토링이 잘 되었습니다. 테스트 코드의 일관성과 유지보수성이 크게 향상되었습니다.


141-141: lenient() 사용 검토 필요

블랙리스트 토큰 테스트에서 lenient() 사용이 필요한지 확인해주세요. strict stubbing 경고를 해결하기 위한 것이라면 적절하지만, 불필요한 모킹을 숨기는 용도라면 모킹 설정을 재검토하는 것이 좋겠습니다.


46-56: 헬퍼 메서드 활용으로 가독성 향상

givenTokenIsNotBlacklisted(), whenValidateAccessToken(), thenTokenValidationShouldSucceed() 등의 헬퍼 메서드 사용으로 Given-When-Then 패턴이 명확해지고 테스트 가독성이 크게 향상되었습니다.


367-385: 통합 헬퍼 메서드를 통한 종합 검증 우수

verifyCompleteTokenValidation()verifyCompleteRefreshTokenValidation() 메서드를 활용하여 토큰 검증의 모든 측면을 종합적으로 검증하는 접근 방식이 뛰어납니다. 테스트의 완전성을 보장합니다.

src/test/java/com/ururulab/ururu/auth/service/AuthServiceTestBase.java (3)

76-144: Given 메서드들의 일관된 구현

테스트 데이터 설정을 위한 Given 메서드들이 명확하고 일관되게 구현되어 있습니다. Member와 Seller의 활성/삭제 상태를 구분하여 처리하는 방식이 적절합니다.


133-136: Lenient stubbing 사용의 적절성

givenTokenIsNotBlacklisted 메서드에서 lenient() 사용은 불필요한 stubbing 경고를 방지하는 좋은 관행입니다.


162-244: 포괄적인 검증 헬퍼 메서드

다양한 예외 상황과 토큰 상태를 검증하는 Then 메서드들이 체계적으로 구현되어 있습니다. 특히 BusinessException과 IllegalArgumentException을 구분하여 처리하는 점이 좋습니다.

- CountDownLatch와 ExecutorService를 활용한 실제 동시성 테스트
- 5개 스레드 동시 실행으로 하나만 성공하는 시나리오 검증
- DataIntegrityViolationException을 통한 중복 데이터 처리 검증
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (2)

460-507: 테스트명과 구현 내용이 불일치합니다

실제로는 동시성 테스트를 구현하고 있지만 테스트명이 "기본 동작 검증"으로 되어 있어 혼란을 야기할 수 있습니다.

테스트명을 실제 구현에 맞게 수정하는 것을 제안합니다:

-    @DisplayName("회원가입 기본 동작 검증")
+    @DisplayName("동시 회원가입 시도 시 하나만 성공")
     class SellerSignupBasicValidationTest {

-        @DisplayName("회원가입 기본 동작 검증")
+        @DisplayName("동시 회원가입 시도 시 하나만 성공")
         void signup_basicValidation_success() throws InterruptedException {

또는 클래스명도 함께 변경:

-    class SellerSignupBasicValidationTest {
+    class SellerSignupConcurrencyTest {

509-535: 성능 테스트 안정성 개선을 고려해보세요

성능 테스트가 잘 구현되어 있습니다. 다만 CI/CD 환경에서의 안정성을 위해 다음을 고려해보세요.

성능 테스트 개선 방안:

         // Then
         assertThat(response).isNotNull();
-        assertThat(endTime - startTime).isLessThan(1000); // 1초 이내 처리
+        // CI/CD 환경의 성능 변동성을 고려하여 여유있는 임계값 설정
+        assertThat(endTime - startTime).isLessThan(5000); // 5초 이내 처리
+        
+        // 또는 조건부 성능 테스트
+        // @EnabledIf("'${test.performance.enabled}' == 'true'")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29435c3 and 6f1f7bf.

📒 Files selected for processing (1)
  • src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: songcw8
PR: UruruLab/Ururu-Backend#149
File: src/main/java/com/ururulab/ururu/global/config/SecurityConfig.java:49-50
Timestamp: 2025-07-11T06:26:59.125Z
Learning: 사용자 songcw8은 보안 관련 피드백(임시 permitAll() 설정 제거 계획 수립)에 대해 적극적으로 대응하고 반영하는 자세를 보이며, 개발 편의성과 보안성 사이의 균형을 이해하고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:213-241
Timestamp: 2025-06-26T16:45:33.604Z
Learning: Ururu-Backend 프로젝트에서 CartService의 validatePurchaseLimit 메서드의 성능 최적화 (CQRS 패턴, UserPurchaseSummary 테이블 등)는 기능 구현 완료 후 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#43
File: src/main/java/com/ururulab/ururu/auth/service/social/KakaoLoginService.java:108-139
Timestamp: 2025-06-24T06:08:49.466Z
Learning: 사용자 23MinL은 KakaoLoginService에서 외부 API 호출(getAccessToken, getMemberInfo)을 트랜잭션 범위에서 분리하여 데이터베이스 연결을 최적화하는 제안에 동의하고 적용하기로 했습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#109
File: src/main/java/com/ururulab/ururu/payment/service/PaymentService.java:157-181
Timestamp: 2025-07-03T04:34:42.502Z
Learning: Ururu-Backend 프로젝트의 PaymentService에서 결제 승인 시 동시성 제어를 위해 Payment 엔티티에 @Version 필드를 추가하여 낙관적 락을 적용하기로 결정했습니다. 이는 기존의 Redis 분산 락과 JPA @Version 낙관적 락을 통한 2단계 보호 메커니즘과 일관성을 유지하는 접근입니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/domain/repository/CartRepository.java:14-27
Timestamp: 2025-06-26T16:47:30.315Z
Learning: Ururu-Backend 프로젝트에서 CartRepository의 복잡한 페치 조인 쿼리(5개의 LEFT JOIN FETCH) 성능 최적화는 기능 구현 완료 후 CQRS 패턴이나 UserPurchaseSummary 테이블 도입을 통해 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 1억원, 수량이 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#38
File: src/main/java/com/ururulab/ururu/order/domain/entity/Order.java:67-96
Timestamp: 2025-06-23T03:48:45.602Z
Learning: Order domain entity에서 필수 필드 검증은 DTO validation으로 처리할 예정입니다. 도메인 엔티티 레벨에서는 비즈니스 로직에 집중하고 입력 검증은 DTO 레이어에서 담당하는 아키텍처 접근법을 사용합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:115-133
Timestamp: 2025-06-26T16:29:03.796Z
Learning: Ururu-Backend 프로젝트에서 CartItem.decreaseQuantity() 메서드는 내부적으로 수량 검증 로직을 구현하고 있으며, 엔티티 레벨에서 도메인 규칙을 관리하는 DDD 원칙을 따라 서비스 레이어에서의 중복 검증을 피하고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/domain/entity/ReviewImage.java:38-39
Timestamp: 2025-06-20T19:50:35.318Z
Learning: Joowon-Seo 프로젝트에서 JPA 엔티티 필드 타입 선택 시 다음 가이드라인을 선호: 1) 필수 불린 플래그는 boolean + 명시적 초기화 사용, 2) 팀 일관성을 위해 원시타입과 래퍼타입 사용 규칙 정립 필요, 3) 데이터베이스 제약조건과 JPA 엔티티 필드 타입 일치시키기 중요
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 PaymentPolicy.MAX_AMOUNT = 100_000_000 (1억원), 수량이 OrderValidationConstants.QUANTITY_MAX = 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (2)
Learnt from: 1000hyehyang
PR: UruruLab/Ururu-Backend#169
File: src/test/java/com/ururulab/ururu/auth/service/AuthServiceTestBase.java:315-320
Timestamp: 2025-07-12T18:02:29.718Z
Learning: 테스트 메서드의 파라미터 순서는 실제 호출하는 메서드의 시그니처와 일치해야 합니다. 테스트 클래스 내에서 인위적인 일관성보다는 실제 메서드 호출과의 일치성을 우선시해야 합니다.
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
🧬 Code Graph Analysis (1)
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1)
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1)
  • SellerTestFixture (16-411)
🔇 Additional comments (7)
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (7)

1-50: 테스트 클래스 설정이 우수합니다

포괄적인 테스트를 위한 적절한 import 구성과 Mock 설정이 잘 되어 있습니다. 클래스 문서화도 명확합니다.


51-111: 정상 케이스 테스트가 철저합니다

이미지 유무에 따른 다양한 시나리오와 모든 의존성 호출을 검증하여 완전한 테스트 커버리지를 제공합니다.


113-215: 중복 검증 테스트가 체계적입니다

이메일 정규화(대소문자, 공백 제거) 후 중복 체크 로직과 검증 순서가 올바르게 테스트되고 있습니다.


243-315: 경계 조건 테스트가 포괄적입니다

최대/최소 길이와 특수문자 케이스를 모두 포함하여 견고한 경계 조건 검증을 제공합니다.


423-458: 예외 처리 테스트가 적절합니다

다양한 예외 상황에 대한 테스트가 체계적으로 구현되어 있습니다.


317-421: 정규화 및 암호화 테스트가 상세합니다

이메일 정규화(대소문자, 공백)와 비밀번호 암호화 로직이 정확히 검증되고 있습니다.


1-536: 매우 우수한 테스트 코드입니다

포괄적인 테스트 커버리지와 체계적인 구조가 인상적입니다. 정상/예외/경계/성능/동시성 시나리오를 모두 포함하여 서비스의 안정성을 보장합니다. SellerTestFixture 활용으로 테스트 데이터 관리도 우수합니다.

@1000hyehyang 1000hyehyang changed the title 판매자 회원가입 테스트 코드 작성 판매자 회원가입 Service계층 테스트 코드 작성 Jul 13, 2025
Copy link
Contributor

@songcw8 songcw8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

판매자 회원가입 서비스 테스트 코드는 정상, 예외, 경계값, 정규화, 성능 등 다양한 시나리오를 종합적으로 잘 커버하고 있습니다! @nested 구조와 SellerTestFixture 기반의 테스트 구성은 가독성과 유지보수성을 높이는 데 큰 도움이 되며, 실제 서비스 로직과의 정합성도 우수하게 반영되어 있습니다. 전체적으로 테스트 품질이 높으며, 꼼꼼하게 잘 구현해주셨습니다. 고생 많으셨습니다!

test: 이메일/비밀번호 최대 길이 경계값 테스트 추가
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (1)
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1)

579-600: 성능 테스트 개선을 고려해보세요

현재 단순히 1초 이내 완료를 검증하는 방식인데, 더 정확한 성능 측정을 위해 여러 번 실행 후 평균값을 측정하거나 JMH 같은 마이크로벤치마크 도구 사용을 고려해볼 수 있습니다.

@Test
@DisplayName("대용량 데이터 처리 성능 테스트")
void signup_largeData_performanceTest() {
    // Given
    SellerSignupRequest request = SellerTestFixture.createRequestWithLargeData();
    String encodedPassword = "encodedPassword123";
    
    given(sellerRepository.isEmailAvailable("large@ururu.shop")).willReturn(true);
    given(sellerRepository.isBusinessNumberAvailable("1234567890")).willReturn(true);
    given(sellerRepository.isNameAvailable("A".repeat(50))).willReturn(true);
    given(passwordEncoder.encode("Password123!")).willReturn(encodedPassword);
    given(sellerRepository.save(any(Seller.class))).willReturn(SellerTestFixture.createSeller(1L, "large@ururu.shop", "A".repeat(50)));

-    // When
-    long startTime = System.currentTimeMillis();
-    SellerResponse response = sellerService.signup(request);
-    long endTime = System.currentTimeMillis();
-
-    // Then
-    assertThat(response).isNotNull();
-    assertThat(endTime - startTime).isLessThan(1000); // 1초 이내 처리
+    // When & Then - 여러 번 실행하여 평균 성능 측정
+    int iterations = 5;
+    long totalTime = 0;
+    
+    for (int i = 0; i < iterations; i++) {
+        long startTime = System.nanoTime();
+        SellerResponse response = sellerService.signup(request);
+        long endTime = System.nanoTime();
+        
+        assertThat(response).isNotNull();
+        totalTime += (endTime - startTime);
+    }
+    
+    long averageTimeMs = totalTime / iterations / 1_000_000;
+    assertThat(averageTimeMs).isLessThan(100); // 평균 100ms 이내 처리
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f1f7bf and 90693ae.

📒 Files selected for processing (2)
  • src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1 hunks)
  • src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: songcw8
PR: UruruLab/Ururu-Backend#149
File: src/main/java/com/ururulab/ururu/global/config/SecurityConfig.java:49-50
Timestamp: 2025-07-11T06:26:59.125Z
Learning: 사용자 songcw8은 보안 관련 피드백(임시 permitAll() 설정 제거 계획 수립)에 대해 적극적으로 대응하고 반영하는 자세를 보이며, 개발 편의성과 보안성 사이의 균형을 이해하고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:213-241
Timestamp: 2025-06-26T16:45:33.604Z
Learning: Ururu-Backend 프로젝트에서 CartService의 validatePurchaseLimit 메서드의 성능 최적화 (CQRS 패턴, UserPurchaseSummary 테이블 등)는 기능 구현 완료 후 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#43
File: src/main/java/com/ururulab/ururu/auth/service/social/KakaoLoginService.java:108-139
Timestamp: 2025-06-24T06:08:49.466Z
Learning: 사용자 23MinL은 KakaoLoginService에서 외부 API 호출(getAccessToken, getMemberInfo)을 트랜잭션 범위에서 분리하여 데이터베이스 연결을 최적화하는 제안에 동의하고 적용하기로 했습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#109
File: src/main/java/com/ururulab/ururu/payment/service/PaymentService.java:157-181
Timestamp: 2025-07-03T04:34:42.502Z
Learning: Ururu-Backend 프로젝트의 PaymentService에서 결제 승인 시 동시성 제어를 위해 Payment 엔티티에 @Version 필드를 추가하여 낙관적 락을 적용하기로 결정했습니다. 이는 기존의 Redis 분산 락과 JPA @Version 낙관적 락을 통한 2단계 보호 메커니즘과 일관성을 유지하는 접근입니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/domain/repository/CartRepository.java:14-27
Timestamp: 2025-06-26T16:47:30.315Z
Learning: Ururu-Backend 프로젝트에서 CartRepository의 복잡한 페치 조인 쿼리(5개의 LEFT JOIN FETCH) 성능 최적화는 기능 구현 완료 후 CQRS 패턴이나 UserPurchaseSummary 테이블 도입을 통해 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 1억원, 수량이 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#38
File: src/main/java/com/ururulab/ururu/order/domain/entity/Order.java:67-96
Timestamp: 2025-06-23T03:48:45.602Z
Learning: Order domain entity에서 필수 필드 검증은 DTO validation으로 처리할 예정입니다. 도메인 엔티티 레벨에서는 비즈니스 로직에 집중하고 입력 검증은 DTO 레이어에서 담당하는 아키텍처 접근법을 사용합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:115-133
Timestamp: 2025-06-26T16:29:03.796Z
Learning: Ururu-Backend 프로젝트에서 CartItem.decreaseQuantity() 메서드는 내부적으로 수량 검증 로직을 구현하고 있으며, 엔티티 레벨에서 도메인 규칙을 관리하는 DDD 원칙을 따라 서비스 레이어에서의 중복 검증을 피하고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/domain/entity/ReviewImage.java:38-39
Timestamp: 2025-06-20T19:50:35.318Z
Learning: Joowon-Seo 프로젝트에서 JPA 엔티티 필드 타입 선택 시 다음 가이드라인을 선호: 1) 필수 불린 플래그는 boolean + 명시적 초기화 사용, 2) 팀 일관성을 위해 원시타입과 래퍼타입 사용 규칙 정립 필요, 3) 데이터베이스 제약조건과 JPA 엔티티 필드 타입 일치시키기 중요
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 PaymentPolicy.MAX_AMOUNT = 100_000_000 (1억원), 수량이 OrderValidationConstants.QUANTITY_MAX = 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1)
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1)
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
🧬 Code Graph Analysis (1)
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (1)
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1)
  • SellerTestFixture (16-468)
🔇 Additional comments (12)
src/test/java/com/ururulab/ururu/seller/service/SellerSignupServiceTest.java (6)

33-40: 테스트 클래스 문서화가 잘 되어 있습니다

Repository 계층만 Mock 처리하고 실제 비즈니스 로직을 검증한다는 명확한 의도가 잘 드러나 있어 테스트의 목적과 범위를 이해하기 쉽습니다.


55-86: 정상 회원가입 테스트가 철저하게 구현되었습니다

Mock 설정, 비즈니스 로직 실행, 응답 검증, 의존성 호출 검증이 모두 포함된 완성도 높은 테스트입니다. 특히 verify를 통한 메서드 호출 검증이 적절합니다.


134-149: 이메일 정규화 검증이 우수합니다

대소문자 변이 시 정규화 후 중복 체크가 수행되는지를 명확히 검증하고 있어, 실제 서비스의 이메일 정규화 로직과 일치하는 테스트입니다.


221-240: DB 제약조건 위반 처리가 적절합니다

DataIntegrityViolationException을 적절한 BusinessException으로 변환하는 로직을 검증하는 중요한 테스트입니다. 실제 운영 환경에서 발생할 수 있는 상황을 잘 시뮬레이션합니다.


247-289: 경계 조건 테스트가 포괄적입니다

최대/최소 길이 경계값 테스트가 잘 구현되어 있어 입력 검증 로직의 안정성을 확보할 수 있습니다. 특히 A".repeat(50) 같은 명시적인 길이 검증이 유용합니다.


532-572: 동시성 테스트가 적절히 구현되었습니다

이전 리뷰 피드백이 반영되어 실제 멀티스레드 환경에서 동시성 제어를 검증하는 테스트로 개선되었습니다. ExecutorServiceCountDownLatch를 사용한 구현이 적절합니다.

src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (6)

10-16: 테스트 픽스처 클래스 설계가 우수합니다

테스트 데이터 중앙화를 통해 유지보수성을 향상시키는 명확한 목적과 이점이 잘 설명되어 있습니다. 객체 생성 방식 변경 시 한 곳에서만 수정 가능하다는 설계 철학이 바람직합니다.


23-39: 팩토리 메서드 패턴이 적절히 적용되었습니다

하드코딩된 테스트 데이터를 사용하지만, 테스트 목적에 적합하며 일관된 데이터 생성을 보장합니다. setSellerId 헬퍼 메서드를 통한 ID 설정도 깔끔합니다.


63-96: 테스트 시나리오별 데이터 생성이 체계적입니다

정상 케이스와 이미지 없는 케이스를 분리하여 제공함으로써 다양한 테스트 시나리오를 지원합니다. null 처리가 명시적으로 되어 있어 좋습니다.


355-407: 경계값 테스트 데이터 생성이 정교합니다

이메일과 비밀번호의 최대 길이를 정확히 계산하여 생성하는 로직이 인상적입니다. 특히 이메일의 경우 48 + 1 + 47 + 4 = 100자 주석으로 계산 과정을 명시한 것이 유용합니다.


414-422: 리플렉션 사용 시 예외 처리가 적절합니다

private 필드 접근을 위한 리플렉션 사용은 테스트 환경에서는 적절하며, 예외 발생 시 명확한 메시지와 함께 RuntimeException으로 래핑하는 것이 좋습니다.


459-467: BaseEntity 필드 설정 헬퍼 메서드가 유용합니다

향후 BaseEntity 구조 변경 시 이 메서드만 수정하면 된다는 설계가 우수합니다. 범용적인 필드 설정 메서드로 확장성을 고려한 설계입니다.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (2)
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (2)

361-361: 이메일 최대 길이 계산 로직을 개선해주세요

현재 하드코딩된 문자열 길이 계산(48 + 1 + 47 + 4 = 100자) 대신 상수를 활용하거나 더 명확한 방식으로 구성하는 것이 좋겠습니다.

-                "a".repeat(48) + "@" + "b".repeat(47) + ".com", // 48 + 1 + 47 + 4 = 100자
+                // EMAIL_MAX_LENGTH(100) = local(48) + @ + domain(47) + .com(4)
+                "a".repeat(48) + "@" + "b".repeat(47) + ".com",

298-312: 빈 필드 테스트 케이스 확장을 고려해보세요

현재는 브랜드명만 빈 값으로 테스트하고 있는데, 다른 필수 필드들에 대한 빈 값 테스트도 추가하면 더 포괄적인 검증이 가능할 것 같습니다.

다음과 같이 추가 메서드들을 고려해보세요:

  • createRequestWithEmptyCompanyName()
  • createRequestWithEmptyRepresentativeName()
  • createRequestWithEmptyEmail()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90693ae and 107613c.

📒 Files selected for processing (1)
  • src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: songcw8
PR: UruruLab/Ururu-Backend#149
File: src/main/java/com/ururulab/ururu/global/config/SecurityConfig.java:49-50
Timestamp: 2025-07-11T06:26:59.125Z
Learning: 사용자 songcw8은 보안 관련 피드백(임시 permitAll() 설정 제거 계획 수립)에 대해 적극적으로 대응하고 반영하는 자세를 보이며, 개발 편의성과 보안성 사이의 균형을 이해하고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:213-241
Timestamp: 2025-06-26T16:45:33.604Z
Learning: Ururu-Backend 프로젝트에서 CartService의 validatePurchaseLimit 메서드의 성능 최적화 (CQRS 패턴, UserPurchaseSummary 테이블 등)는 기능 구현 완료 후 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#43
File: src/main/java/com/ururulab/ururu/auth/service/social/KakaoLoginService.java:108-139
Timestamp: 2025-06-24T06:08:49.466Z
Learning: 사용자 23MinL은 KakaoLoginService에서 외부 API 호출(getAccessToken, getMemberInfo)을 트랜잭션 범위에서 분리하여 데이터베이스 연결을 최적화하는 제안에 동의하고 적용하기로 했습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#109
File: src/main/java/com/ururulab/ururu/payment/service/PaymentService.java:157-181
Timestamp: 2025-07-03T04:34:42.502Z
Learning: Ururu-Backend 프로젝트의 PaymentService에서 결제 승인 시 동시성 제어를 위해 Payment 엔티티에 @Version 필드를 추가하여 낙관적 락을 적용하기로 결정했습니다. 이는 기존의 Redis 분산 락과 JPA @Version 낙관적 락을 통한 2단계 보호 메커니즘과 일관성을 유지하는 접근입니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/domain/repository/CartRepository.java:14-27
Timestamp: 2025-06-26T16:47:30.315Z
Learning: Ururu-Backend 프로젝트에서 CartRepository의 복잡한 페치 조인 쿼리(5개의 LEFT JOIN FETCH) 성능 최적화는 기능 구현 완료 후 CQRS 패턴이나 UserPurchaseSummary 테이블 도입을 통해 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 1억원, 수량이 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#38
File: src/main/java/com/ururulab/ururu/order/domain/entity/Order.java:67-96
Timestamp: 2025-06-23T03:48:45.602Z
Learning: Order domain entity에서 필수 필드 검증은 DTO validation으로 처리할 예정입니다. 도메인 엔티티 레벨에서는 비즈니스 로직에 집중하고 입력 검증은 DTO 레이어에서 담당하는 아키텍처 접근법을 사용합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:115-133
Timestamp: 2025-06-26T16:29:03.796Z
Learning: Ururu-Backend 프로젝트에서 CartItem.decreaseQuantity() 메서드는 내부적으로 수량 검증 로직을 구현하고 있으며, 엔티티 레벨에서 도메인 규칙을 관리하는 DDD 원칙을 따라 서비스 레이어에서의 중복 검증을 피하고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/domain/entity/ReviewImage.java:38-39
Timestamp: 2025-06-20T19:50:35.318Z
Learning: Joowon-Seo 프로젝트에서 JPA 엔티티 필드 타입 선택 시 다음 가이드라인을 선호: 1) 필수 불린 플래그는 boolean + 명시적 초기화 사용, 2) 팀 일관성을 위해 원시타입과 래퍼타입 사용 규칙 정립 필요, 3) 데이터베이스 제약조건과 JPA 엔티티 필드 타입 일치시키기 중요
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 PaymentPolicy.MAX_AMOUNT = 100_000_000 (1억원), 수량이 OrderValidationConstants.QUANTITY_MAX = 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (2)
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
🔇 Additional comments (6)
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (6)

23-58: 기본 판매자 데이터 생성 메서드 구조가 잘 설계되었습니다

ID 포함/불포함 버전으로 오버로딩된 팩토리 메서드들이 테스트 시나리오의 유연성을 잘 제공하고 있습니다. 리플렉션을 통한 ID 설정도 적절하게 분리되어 있어 캡슐화를 유지하면서 테스트 편의성을 확보했습니다.


63-96: 이미지 유무에 따른 테스트 케이스 분리가 유용합니다

nullable 필드인 이미지에 대해 별도의 팩토리 메서드를 제공하여 테스트 시나리오를 명확하게 구분할 수 있도록 했습니다. 이는 옵셔널 필드 테스트에 매우 유용한 접근입니다.


103-155: 중복 검증 테스트 데이터가 체계적으로 구성되었습니다

이메일, 사업자등록번호, 브랜드명 각각에 대한 중복 케이스를 별도로 제공하여 개별 검증 로직 테스트가 가능하도록 설계되었습니다. 각 메서드명도 의도를 명확하게 표현하고 있습니다.


414-422: 리플렉션 사용 시 예외 처리가 적절합니다

private 필드 접근을 위한 리플렉션 사용이 테스트 환경에서는 불가피하며, RuntimeException으로 래핑하여 테스트 실패를 명확하게 표시하는 접근이 적절합니다.


427-440: BaseEntity 필드 접근 방식이 안정적입니다

상속 구조에서 부모 클래스의 필드에 명시적으로 접근하여 안정성을 높였습니다. 주석으로 의도를 명확히 표현한 점도 좋습니다.


220-253: 테스트 경계값 검증 완료

테스트에서 사용된 반복 길이 값이 SellerConstants에 정의된 컬럼 길이 제약과 정확히 일치합니다:

  • NAME_MAX_LENGTH (50) → "A".repeat(50)
  • BUSINESS_NAME_MAX_LENGTH (100) → "B".repeat(100)
  • OWNER_NAME_MAX_LENGTH (50) → "C".repeat(50)
  • ADDRESS_MAX_LENGTH (100) → "D".repeat(100), "E".repeat(100)
  • MAIL_ORDER_NUMBER_MAX_LENGTH (50) → "F".repeat(50)

또한 createRequestWithMinLength()@NotBlank 기준 최소 1자 테스트(“A”, “B”, …)로 올바르게 구성되어 있습니다.

- 사용되지 않는 setBaseEntityField 메서드 제거 (459-467행)
- BaseEntity 필드는 이미 전용 메서드로 처리되고 있음
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 107613c and fdd3fe6.

📒 Files selected for processing (1)
  • src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: songcw8
PR: UruruLab/Ururu-Backend#149
File: src/main/java/com/ururulab/ururu/global/config/SecurityConfig.java:49-50
Timestamp: 2025-07-11T06:26:59.125Z
Learning: 사용자 songcw8은 보안 관련 피드백(임시 permitAll() 설정 제거 계획 수립)에 대해 적극적으로 대응하고 반영하는 자세를 보이며, 개발 편의성과 보안성 사이의 균형을 이해하고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:213-241
Timestamp: 2025-06-26T16:45:33.604Z
Learning: Ururu-Backend 프로젝트에서 CartService의 validatePurchaseLimit 메서드의 성능 최적화 (CQRS 패턴, UserPurchaseSummary 테이블 등)는 기능 구현 완료 후 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: 23MinL
PR: UruruLab/Ururu-Backend#43
File: src/main/java/com/ururulab/ururu/auth/service/social/KakaoLoginService.java:108-139
Timestamp: 2025-06-24T06:08:49.466Z
Learning: 사용자 23MinL은 KakaoLoginService에서 외부 API 호출(getAccessToken, getMemberInfo)을 트랜잭션 범위에서 분리하여 데이터베이스 연결을 최적화하는 제안에 동의하고 적용하기로 했습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#109
File: src/main/java/com/ururulab/ururu/payment/service/PaymentService.java:157-181
Timestamp: 2025-07-03T04:34:42.502Z
Learning: Ururu-Backend 프로젝트의 PaymentService에서 결제 승인 시 동시성 제어를 위해 Payment 엔티티에 @Version 필드를 추가하여 낙관적 락을 적용하기로 결정했습니다. 이는 기존의 Redis 분산 락과 JPA @Version 낙관적 락을 통한 2단계 보호 메커니즘과 일관성을 유지하는 접근입니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/domain/repository/CartRepository.java:14-27
Timestamp: 2025-06-26T16:47:30.315Z
Learning: Ururu-Backend 프로젝트에서 CartRepository의 복잡한 페치 조인 쿼리(5개의 LEFT JOIN FETCH) 성능 최적화는 기능 구현 완료 후 CQRS 패턴이나 UserPurchaseSummary 테이블 도입을 통해 추후 적용 예정이며, 현재는 기능 구현에 우선순위를 두고 있습니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 1억원, 수량이 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#38
File: src/main/java/com/ururulab/ururu/order/domain/entity/Order.java:67-96
Timestamp: 2025-06-23T03:48:45.602Z
Learning: Order domain entity에서 필수 필드 검증은 DTO validation으로 처리할 예정입니다. 도메인 엔티티 레벨에서는 비즈니스 로직에 집중하고 입력 검증은 DTO 레이어에서 담당하는 아키텍처 접근법을 사용합니다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#71
File: src/main/java/com/ururulab/ururu/order/service/CartService.java:115-133
Timestamp: 2025-06-26T16:29:03.796Z
Learning: Ururu-Backend 프로젝트에서 CartItem.decreaseQuantity() 메서드는 내부적으로 수량 검증 로직을 구현하고 있으며, 엔티티 레벨에서 도메인 규칙을 관리하는 DDD 원칙을 따라 서비스 레이어에서의 중복 검증을 피하고 있습니다.
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#27
File: src/main/java/com/ururulab/ururu/review/domain/entity/ReviewImage.java:38-39
Timestamp: 2025-06-20T19:50:35.318Z
Learning: Joowon-Seo 프로젝트에서 JPA 엔티티 필드 타입 선택 시 다음 가이드라인을 선호: 1) 필수 불린 플래그는 boolean + 명시적 초기화 사용, 2) 팀 일관성을 위해 원시타입과 래퍼타입 사용 규칙 정립 필요, 3) 데이터베이스 제약조건과 JPA 엔티티 필드 타입 일치시키기 중요
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#87
File: src/main/java/com/ururulab/ururu/order/domain/dto/response/OrderItemResponse.java:6-12
Timestamp: 2025-06-29T15:42:04.548Z
Learning: Ururu-Backend 프로젝트에서는 주문 금액이 PaymentPolicy.MAX_AMOUNT = 100_000_000 (1억원), 수량이 OrderValidationConstants.QUANTITY_MAX = 999개로 비즈니스 제약이 validation을 통해 명시적으로 제한되어 있어 Integer 타입 사용이 안전하며, 도메인 컨텍스트를 고려하지 않은 일반론적 타입 변경 제안은 부적절합니다.
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (3)
Learnt from: Joowon-Seo
PR: UruruLab/Ururu-Backend#31
File: src/main/java/com/ururulab/ururu/review/service/ReviewService.java:37-41
Timestamp: 2025-06-21T10:55:19.543Z
Learning: Ururu-Backend 프로젝트에서 Product 도메인이 아직 개발되지 않은 상태이며, ReviewService에서 static Product 인스턴스를 임시 해결책으로 사용하고 있다. ProductRepository 구현 완료 후 동적 검증 로직으로 교체할 예정이다.
Learnt from: taehyun32
PR: UruruLab/Ururu-Backend#38
File: src/main/java/com/ururulab/ururu/order/domain/entity/Order.java:67-96
Timestamp: 2025-06-23T03:48:45.602Z
Learning: Order domain entity에서 필수 필드 검증은 DTO validation으로 처리할 예정입니다. 도메인 엔티티 레벨에서는 비즈니스 로직에 집중하고 입력 검증은 DTO 레이어에서 담당하는 아키텍처 접근법을 사용합니다.
Learnt from: nan0silver
PR: UruruLab/Ururu-Backend#118
File: src/main/java/com/ururulab/ururu/global/config/loader/SellerSampleDataLoader.java:35-35
Timestamp: 2025-07-04T01:13:47.809Z
Learning: Ururu-Backend 프로젝트에서 SellerSampleDataLoader와 같은 샘플 데이터 로더 클래스에서는 개발 및 테스트 목적으로 하드코딩된 비밀번호 사용을 허용하고 있으며, 이는 샘플 데이터 주입의 실용적인 필요에 의한 선택입니다.
🔇 Additional comments (3)
src/test/java/com/ururulab/ururu/seller/service/SellerTestFixture.java (3)

10-16: 테스트 픽스처 클래스 구조가 우수합니다

테스트 데이터 중앙화를 통한 일관성 향상과 유지보수성 개선이 잘 구현되었습니다. 다양한 테스트 시나리오를 체계적으로 분류하여 제공하고 있습니다.


414-453: 리플렉션 기반 유틸리티 메서드가 적절합니다

테스트 환경에서 private 필드 설정을 위한 리플렉션 사용이 적절하며, 예외 처리도 RuntimeException으로 래핑하여 테스트 실패를 명확하게 표시하고 있습니다. BaseEntity 클래스를 명시적으로 참조하여 안정성을 높인 점도 좋습니다.


177-253: 경계 조건 테스트 데이터가 포괄적입니다

이메일 대소문자 변이, 공백 처리, 최대/최소 길이 등 다양한 경계 조건을 커버하는 테스트 데이터가 잘 구성되어 있습니다. 실제 서비스에서 발생할 수 있는 다양한 입력 패턴을 고려한 좋은 설계입니다.

- createRequestWithMaxPasswordLength 메서드의 비밀번호 길이 수정
- createRequestWithMaxEmailAndPasswordLength 메서드의 비밀번호 길이 수정
- "1!@#" → "1!@#$"로 변경하여 정확히 50자 맞춤
- 기존: 25 + 20 + 4 = 49자
- 수정: 25 + 20 + 5 = 50자
- 최대 길이 경계값 테스트의 정확성 보장
@1000hyehyang 1000hyehyang merged commit e0057d8 into main Jul 13, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔥 BE 백엔드 이슈 🛠️ Refactor 리팩터링 이슈 ✅ Test 테스트 이슈

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants