Skip to content

Conversation

@pokerbearkr
Copy link
Contributor

@pokerbearkr pokerbearkr commented Jun 12, 2025


작업 내용

  • 소셜 로그인 시에 닉네임 수식어 + 명사 + 숫자로 생성기능 추가

변경 사항


트러블 슈팅


해결해야 할 문제


참고 사항


코드 리뷰 전 확인 체크리스트

  • 불필요한 콘솔 로그, 주석 제거
  • 커밋 메시지 컨벤션 준수 (type : )
  • 기능 정상 동작 확인

Summary by CodeRabbit

  • 신규 기능

    • 닉네임 중복 여부를 확인하는 기능이 추가되었습니다.
    • 무작위 형용사, 동물명, 숫자를 조합해 고유한 닉네임을 자동 생성하는 기능이 도입되었습니다.
    • 회원 가입 시 고유 닉네임이 자동으로 부여됩니다.
    • 탈퇴한 사용자 접근 시 예외 처리가 추가되었습니다.
  • 기타

    • 다양한 한국어 형용사와 동물명이 포함된 닉네임 조합을 위한 목록이 추가되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Jun 12, 2025

Caution

Review failed

The pull request is closed.

"""

Walkthrough

OAuth2 사용자 생성 시 별명을 자동으로 생성하고, 중복되지 않는 별명인지 검증하는 기능이 추가되었습니다. 이를 위해 별명 생성을 위한 형용사와 명사 enum이 도입되었고, 별명 존재 여부를 확인하는 메서드가 저장소 계층에 추가되었습니다. User 엔터티의 팩토리 메서드 시그니처도 변경되었습니다.

Changes

파일/그룹 변경 요약
.../domain/user/model/entity/User.java googleUser, githubUser 팩토리 메서드에 nickname 파라미터 추가
.../domain/user/model/enums/Adjective.java,
.../Noun.java
한국어 형용사, 명사 enum 신설
.../domain/user/repository/UserRepository.java,
.../UserJpaRepository.java,
.../UserRepositoryImpl.java
existsByNickname(String nickname) 메서드 추가
.../domain/user/service/UserDomainService.java 별명 생성 및 중복 체크 메서드 추가
.../domain/user/service/CustomOAuth2UserService.java 별명 생성 로직 적용, UserDomainService 의존성 추가

Sequence Diagram(s)

sequenceDiagram
    participant OAuth2UserService
    participant UserDomainService
    participant UserRepository

    OAuth2UserService->>UserRepository: findByEmail(email)
    alt User not found
        OAuth2UserService->>UserDomainService: generateUniqueNickname()
        UserDomainService->>UserRepository: existsByNickname(nickname) (최대 1천만회 반복)
        UserDomainService-->>OAuth2UserService: unique nickname 반환
        OAuth2UserService->>User: googleUser(email, username, nickname)
        OAuth2UserService->>UserRepository: save(user)
    else User exists
        OAuth2UserService-->>OAuth2UserService: 기존 유저 반환
    end
Loading

Possibly related PRs

  • feat : 닉네임 한글로 랜덤 생성 #56: 동일한 User 엔터티의 googleUsergithubUser 팩토리 메서드 변경과 별명 생성 관련 기능 추가를 포함한 PR로, 본 PR과 직접적인 연관이 있음.

Suggested reviewers

  • thezz9
  • Kimminu7

Poem

🐰
별명 짓는 토끼가 깡총깡총,
형용사 명사 골라서 뚝딱!
중복 없는 이름 찾으려
1천만 번도 도전해요.
이제 우리 유저님,
멋진 별명으로 로그인해요!
🐇✨
"""


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5ea4862 and f1ac92d.

📒 Files selected for processing (1)
  • src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (2 hunks)
✨ 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

@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

🧹 Nitpick comments (8)
src/main/java/org/ezcode/codetest/domain/user/model/enums/Noun.java (1)

3-14: Enum 상수의 표기·타이포 확인 필요

  1. Java 코딩 컨벤션상 enum 상수는 대문자·언더스코어로 작성하는 것이 일반적입니다. 한글로 작성해도 컴파일은 되지만, 혼합 언어 사용 시 IDE 검색·정렬·리팩터링 지원이 떨어집니다. 팀 컨벤션을 한 번 더 확인해주세요.
  2. 7행 다람이 는 일반적으로 ‘다람쥐’의 오타로 보입니다. 타이포인지 의도된 별칭인지 검토 바랍니다.
- 다람이
+ 다람쥐   // 또는 의도한 다른 동물명으로 수정
src/main/java/org/ezcode/codetest/domain/user/model/enums/Adjective.java (1)

3-14: Enum 상수 네이밍 컨벤션 일관성

Noun 과 동일하게 모든 상수가 한글 소문자로 구성되어 있습니다. 코드스타일 규칙(예: GOOGLE JAVA STYLE)에서는 멋있는멋있는 과 같이 대문자·언더스코어로 표기(MEOT_IT_NEUN)하도록 권장합니다.
팀 내부 규칙이 없다면 추후 영문/숫자 혼합 프로젝트에서의 혼란을 줄이기 위해 컨벤션을 정의해 두시는 편이 좋습니다.

src/main/java/org/ezcode/codetest/domain/user/repository/UserRepository.java (1)

18-21: existsByNickname 추가 👍 — Nullable 방어만 검토

메서드 자체는 필요한 기능을 깔끔히 추가했습니다. 다만 외부 호출자가 null 을 전달할 여지가 있으면 NPE 대신 IllegalArgumentException 등으로 방어하거나, 파라미터에 @NonNull/@NotBlank 어노테이션을 붙여 명시해두면 좋겠습니다.

src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserJpaRepository.java (1)

14-14: 닉네임 컬럼에 Unique Index 권장

existsByNickname 빈번 호출 시 풀스캔을 피하려면 DB 레벨에서 nickname 컬럼에 UNIQUE + INDEX를 동시에 걸어두는 것이 좋습니다.
JPA 스키마 자동 생성 중이라면 Entity 쪽에 @Column(unique = true)@Index(columnList = "nickname") 추가를 검토해주세요.

src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserRepositoryImpl.java (1)

41-44: 읽기 전용 트랜잭션 플래그 추가 고려

단순 존재 여부 조회는 쓰기 작업이 없으므로

@Transactional(readOnly = true)

를 붙여주면 불필요한 flush 체크를 피할 수 있습니다. 다른 조회 메서드에도 동일 규칙 적용을 검토해주세요.

src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java (3)

45-47: 불필요한 이중 세미콜론 제거

orElseThrow(...);; 처럼 세미콜론이 두 번 들어가 있습니다. 컴파일에는 영향이 없지만 가독성을 떨어뜨립니다.

- .orElseThrow(() -> new AuthException(AuthExceptionCode.USER_NOT_FOUND));;
+ .orElseThrow(() -> new AuthException(AuthExceptionCode.USER_NOT_FOUND));

74-82: 닉네임 중복 검사 루프 한계 및 동시성 이슈

  1. 최대 1,000만 회 루프는 최악의 경우 긴 지연을 유발할 수 있습니다.
  2. DB UNIQUE 제약만으로도 동시성 중복을 완전히 막을 수 없으므로, 생성 → INSERT 시 충돌이 나면 재시도하는 방식이 더 안전합니다.
for (int i = 0; i < MAX_RETRY; i++) {
    String nickname = generateRandomNickname();
    try {
        userRepository.createNickname(nickname); // 닉네임만 삽입 (unique key)
        return nickname;
    } catch (DuplicateKeyException ignored) {
        // 충돌 → 재시도
    }
}
throw new IllegalStateException("닉네임 생성 실패");

84-89: 닉네임 구성 가독성 개선

adjective.name() + noun.name() + number 로 연결하면 숫자가 1자리일 때 ...호랑이3처럼 가독성이 떨어집니다.
다음과 같이 구분자와 0-padding을 추가하면 사용자 경험이 좋아집니다.

-return adjective.name() + noun.name() + number;
+return String.format("%s%s%03d", adjective.name(), noun.name(), number);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4c8b11b and 7900d18.

📒 Files selected for processing (8)
  • src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java (1 hunks)
  • src/main/java/org/ezcode/codetest/domain/user/model/enums/Adjective.java (1 hunks)
  • src/main/java/org/ezcode/codetest/domain/user/model/enums/Noun.java (1 hunks)
  • src/main/java/org/ezcode/codetest/domain/user/repository/UserRepository.java (1 hunks)
  • src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (2 hunks)
  • src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserJpaRepository.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserRepositoryImpl.java (1 hunks)

Comment on lines +55 to 57
String nickname = userDomainService.generateUniqueNickname();
User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
log.info("newUser: {} 새로운 유저", newUser);
Copy link

@coderabbitai coderabbitai bot Jun 12, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

닉네임 생성 실패 시 예외 유형 매핑 필요

userDomainService.generateUniqueNickname() 내부에서 IllegalStateException이 발생할 수 있는데, 현재 메서드에서는 그대로 전파되어 OAuth2AuthenticationException으로 래핑되지 않습니다.
OAuth 흐름에서 발생하는 모든 예외를 OAuth2AuthenticationException으로 맞춰두면 필터 단계에서 일관되게 처리할 수 있으므로, 아래와 같이 예외 매핑을 권장합니다.

try {
+    String nickname = userDomainService.generateUniqueNickname();
+    User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
+    userRepository.createUser(newUser);
-    String nickname = userDomainService.generateUniqueNickname();
-    User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
-    userRepository.createUser(newUser);
} catch (IllegalStateException e) {
    log.error("중복 닉네임 생성 실패 : {}", e.getMessage());
    throw new OAuth2AuthenticationException("닉네임 생성 실패입니다");
} catch (Exception e) {
    ...
}

generateUniqueNickname 메서드 정의와 CustomOAuth2UserService 내 호출 부분을 확인하기 위해 아래 스크립트를 실행하겠습니다.


🏁 Script executed:

#!/bin/bash
set -e

echo "=== generateUniqueNickname 정의 위치 및 예외 선언 확인 ==="
rg -n "generateUniqueNickname" -C3 src

echo ""
echo "=== CustomOAuth2UserService 내 호출 위치 및 예외 처리 현황 ==="
rg -n "generateUniqueNickname" -C10 src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java

Length of output: 2724


generateUniqueNickname 메서드의 구현 전체와 IllegalStateException 발생 지점을 확인하기 위해 아래 스크립트를 실행하겠습니다.


🏁 Script executed:

#!/bin/bash
set -e

echo "=== generateUniqueNickname 전체 구현 확인 ==="
rg -n "public String generateUniqueNickname" -C20 src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java

echo ""
echo "=== IllegalStateException throw 여부 확인 ==="
rg -n "throw new IllegalStateException" -C2 src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java

Length of output: 1814


닉네임 생성 실패 예외 매핑 추가 필요

UserDomainService.generateUniqueNickname()는 1천만 번 시도 후에도 고유 닉네임을 찾지 못하면
IllegalStateException("중복된 닉네임 생성 불가")를 던집니다.
현재 CustomOAuth2UserService에서는 이 예외가 try 블록 바깥에 있어 필터 단계에서 일관된 OAuth2AuthenticationException 처리 경로를 타지 못합니다.
아래처럼 try 범위를 확장해 IllegalStateException을 별도로 잡아 OAuth2AuthenticationException으로 변환해 주세요.

  • 대상 파일:
    src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (54~64행)
@@ if (findUser == null) {
-    String nickname = userDomainService.generateUniqueNickname();
-    User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
-    log.info("newUser: {} 새로운 유저", newUser);
-    try {
-        userRepository.createUser(newUser);
-    } catch (Exception e) {
-        log.error("OAuth 사용자 생성 실패 : {}", e.getMessage());
-        throw new OAuth2AuthenticationException("사용자 생성 실패입니다");
-    }
+    try {
+        String nickname = userDomainService.generateUniqueNickname();
+        User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
+        log.info("newUser: {} 새로운 유저", newUser);
+        userRepository.createUser(newUser);
+    } catch (IllegalStateException e) {
+        log.error("중복 닉네임 생성 실패 : {}", e.getMessage());
+        throw new OAuth2AuthenticationException("닉네임 생성 실패입니다");
+    } catch (Exception e) {
+        log.error("OAuth 사용자 생성 실패 : {}", e.getMessage());
+        throw new OAuth2AuthenticationException("사용자 생성 실패입니다");
+    }

위 변경을 통해 닉네임 생성 실패 시에도 OAuth2 필터 단계에서 일관된 예외 처리 흐름이 보장됩니다.

📝 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.

Suggested change
String nickname = userDomainService.generateUniqueNickname();
User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
log.info("newUser: {} 새로운 유저", newUser);
if (findUser == null) {
try {
String nickname = userDomainService.generateUniqueNickname();
User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
log.info("newUser: {} 새로운 유저", newUser);
userRepository.createUser(newUser);
} catch (IllegalStateException e) {
log.error("중복 닉네임 생성 실패 : {}", e.getMessage());
throw new OAuth2AuthenticationException("닉네임 생성 실패입니다");
} catch (Exception e) {
log.error("OAuth 사용자 생성 실패 : {}", e.getMessage());
throw new OAuth2AuthenticationException("사용자 생성 실패입니다");
}
}
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java
around lines 54 to 64, the call to userDomainService.generateUniqueNickname()
can throw IllegalStateException which is not currently caught and wrapped as
OAuth2AuthenticationException. To fix this, expand the try block to include the
nickname generation call and catch IllegalStateException separately, then wrap
and rethrow it as an OAuth2AuthenticationException. This ensures consistent
exception handling in the OAuth2 filter layer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

합당한데?

Copy link

Choose a reason for hiding this comment

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

@pokerbearkr 말씀해주신 대로 예외 매핑을 적용하도록 하겠습니다. 아래 계획대로 CustomOAuth2UserService 에 try-catch 블록을 확장하여 IllegalStateExceptionOAuth2AuthenticationException 으로 변환하는 코드를 반영하겠습니다. 확인 후 진행해도 괜찮을지 알려주세요!

• CustomOAuth2UserService 의 findUser == null 분기 내 로직을 try-catch 블록으로 감싸고,
IllegalStateException 을 별도로 잡아 OAuth2AuthenticationException("닉네임 생성 실패입니다") 로 래핑
→ OAuth2 필터 단계에서 일관된 예외 처리 보장

</plan_code_changes>


⏳ Preparing changes...

Copy link

Choose a reason for hiding this comment

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

A summary of the edits CodeRabbit can apply:

CustomOAuth2UserService.java will be updated so that nickname generation and user creation are executed inside a try-catch block which converts IllegalStateException to an OAuth2AuthenticationException, ensuring consistent OAuth error handling.

A plan of each step that CodeRabbit will take in order to execute the edits for each file (with inline rough draft snippets):

✏️ src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java

Delete the current block spanning lines 55-63 (the standalone nickname generation, new User creation, and single Exception catch).


Insert the following replacement starting at line 55:\njava\n try {\n String nickname = userDomainService.generateUniqueNickname();\n User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);\n log.info(\"newUser: {} 새로운 유저\", newUser);\n userRepository.createUser(newUser);\n } catch (IllegalStateException e) {\n log.error(\"중복 닉네임 생성 실패 : {}\", e.getMessage());\n throw new OAuth2AuthenticationException(\"닉네임 생성 실패입니다\");\n } catch (Exception e) {\n log.error(\"OAuth 사용자 생성 실패 : {}\", e.getMessage());\n throw new OAuth2AuthenticationException(\"사용자 생성 실패입니다\");\n }\n


No additional imports are necessary because IllegalStateException is part of java.lang; ensure existing imports remain untouched.


Re-compile and run the OAuth flow (or unit tests that simulate nickname collision) to verify IllegalStateException is now translated into OAuth2AuthenticationException and handled uniformly by the filter layer.

  • ✅ Create PR with these edits
  • 📌 Create commit in current branch
  • 📋 Get copyable edits

Comment on lines +94 to 104
public static User googleUser(String email, String username, String nickname){
return User.builder()
.email(email)
.username(username)
.authType(AuthType.GOOGLE)
.nickname("user_" + UUID.randomUUID().toString().split("-")[0])//닉네임은 자동으로 생성해주고, 나중에 수정할 수 있도록 함
.nickname(nickname)//닉네임은 자동으로 생성해주고, 나중에 수정할 수 있도록 함
.tier(Tier.NEWBIE)
.role(UserRole.USER)
.isDeleted(false)
.password(UUID.randomUUID().toString())
.build();
Copy link

@coderabbitai coderabbitai bot Jun 12, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

랜덤 비밀번호 평문 저장은 보안 위험

OAuth 가입 시 password(UUID.randomUUID().toString())로 무작위 문자열을 그대로 저장하고 있습니다.
비밀번호를 사용하지 않는 계정이라면 NULL 처리하거나, 최소한 PasswordEncoder로 해싱한 값을 저장하여 평문 노출을 방지해주세요.

- .password(UUID.randomUUID().toString())
+ // OAuth 계정은 비밀번호 미사용 → NULL 처리
+ .password(null)

또는,

- .password(UUID.randomUUID().toString())
+ .password(PasswordEncoderFactories.createDelegatingPasswordEncoder()
+            .encode(UUID.randomUUID().toString()))

Also applies to: 107-118

🤖 Prompt for AI Agents
In src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java around
lines 94 to 104 and 107 to 118, the code stores a random password as plain text
for OAuth users, which is a security risk. To fix this, either set the password
field to null if it is not used or encode the random password using
PasswordEncoder before saving it to avoid storing plain text passwords.

Copy link
Collaborator

Choose a reason for hiding this comment

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

알아서할게 토끼야

Copy link

Choose a reason for hiding this comment

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

@Kimminu7 알겠습니다! 필요하시면 언제든지 말씀해 주세요.

@pokerbearkr pokerbearkr merged commit 3bbae9e into dev Jun 12, 2025
2 checks passed
@pokerbearkr pokerbearkr deleted the feat/naming branch June 12, 2025 11:42
@pokerbearkr pokerbearkr added the enhancement New feature or request label Jun 12, 2025
@coderabbitai coderabbitai bot mentioned this pull request Sep 6, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants