refactor: OAuth 서비스 네이밍 통일 및 AI 프롬프트 구조화#63
Conversation
- OAuthUserService → OAuthService로 네이밍 변경 (Google, Kakao, Naver) - Gemini DTO 클래스 5개 삭제 및 서비스 단순화 - WritingStyle 프롬프트를 구조화된 템플릿으로 개선 - AiSummaryResult DTO 추가로 AI 응답 처리 구조화 - 커스텀 문체 스타일 엔티티에 필드 추가 - 관련 테스트 코드 업데이트
|
Caution Review failedThe pull request is closed. Note
|
| Cohort / File(s) | Summary |
|---|---|
OAuth 서비스 리팩토링 src/main/java/com/mylog/domain/auth/service/oauth/OAuthService.java, src/main/java/com/mylog/domain/auth/service/oauth/OAuthServiceFactory.java, src/main/java/com/mylog/domain/auth/service/oauth/impl/GoogleOAuthService.java, src/main/java/com/mylog/domain/auth/service/oauth/impl/KakaoOAuthService.java, src/main/java/com/mylog/domain/auth/service/oauth/impl/NaverOAuthService.java, src/main/java/com/mylog/domain/auth/AuthController.java |
인터페이스 OAuthUserService → OAuthService 이름 변경, 팩토리 클래스명 및 메서드명 통일 (getOAuthUserService → getOAuthService) |
AI 요약 및 태그 처리 개선 src/main/java/com/mylog/domain/article/service/AiService.java, src/main/java/com/mylog/domain/article/service/TagWriter.java, src/main/java/com/mylog/domain/article/service/ArticleReader.java, src/main/java/com/mylog/domain/article/service/ArticleWriter.java |
AI 기반 요약 JSON 파싱, 태그 저장 로직 추가(saveAiTags), TagReader → ArticleTagRepository 변경, ArticleWriter에서 직접 태그 저장 제거 |
요청 DTO 간소화 src/main/java/com/mylog/domain/article/dto/request/ArticleCreateRequest.java, src/main/java/com/mylog/domain/article/dto/request/ArticleUpdateRequest.java |
tagNames 필드 제거, AI 기반 태그 생성으로 전환 |
API 엔드포인트 확장 src/main/java/com/mylog/domain/article/ArticleController.java, src/main/java/com/mylog/domain/article/ArticleService.java, src/main/java/com/mylog/domain/article/dto/AiSummaryResult.java, src/main/java/com/mylog/domain/article/dto/request/Temp.java |
POST /api/articles/summary 새 엔드포인트 추가, Temp 요청 타입 신규, AiSummaryResult 응답 타입 신규 |
Gemini DTO 제거 src/main/java/com/mylog/external/gemini/dto/GeminiRequest.java, src/main/java/com/mylog/external/gemini/dto/GeminiResponse.java, src/main/java/com/mylog/external/gemini/dto/Candidate.java, src/main/java/com/mylog/external/gemini/dto/Content.java, src/main/java/com/mylog/external/gemini/dto/Part.java |
Gemini API 응답 구조 DTO 제거, JSON 직렬화 단순화 |
글쓰기 스타일 템플릿 강화 src/main/java/com/mylog/common/enums/WritingStyle.java, src/main/java/com/mylog/domain/member/entity/CustomWritingStyle.java |
단일행 문자열 → Java 텍스트 블록으로 변경, Role/Task/Constraint/Instruction 섹션 구조화 |
예외 처리 및 설정 정리 src/main/java/com/mylog/common/exception/ErrorCode.java, src/main/java/com/mylog/common/exception/GlobalExceptionHandler.java, src/main/java/com/mylog/external/gemini/GeminiService.java |
NOT_LOGGED_IN 제거, 예외 핸들러 중복 제거, Gemini 로깅 제거 |
테스트 업데이트 src/test/java/com/mylog/domain/article/service/ArticleReaderTest.java, src/test/java/com/mylog/domain/article/service/ArticleServiceTest.java, src/test/java/com/mylog/domain/article/service/ArticleWriterTest.java, src/test/java/com/mylog/domain/article/service/TagWriterTest.java |
TagReader → ArticleTagRepository 모킹 변경, AI 태그 기반 테스트 시나리오 추가, 직접 태그 저장 테스트 제거 |
기타 설정 및 정리 compose.dev.yml, src/main/java/com/mylog/common/response/BaseResponse.java, src/main/java/com/mylog/common/response/ErrorResponse.java, src/main/java/com/mylog/common/security/SecurityConfig.java, src/main/java/com/mylog/config/AsyncConfig.java, src/main/java/com/mylog/domain/member/MemberController.java |
Redis 설정 추가, 응답 DTO ErrorDetail 추가, 불필요한 주석 제거 |
Sequence Diagram(s)
sequenceDiagram
actor Client
participant ArticleController
participant ArticleService
participant AiService
participant GeminiAPI
participant TagWriter
participant ArticleTagRepository
Client->>ArticleController: POST /api/articles/summary<br/>(Temp request)
ArticleController->>ArticleService: getArticleSummary(Temp)
ArticleService->>AiService: test(content)
AiService->>GeminiAPI: callGemini(prompt)
GeminiAPI-->>AiService: JSON 응답<br/>(summary + tags)
AiService->>AiService: parseAiSummaryResponse()<br/>(JSON 파싱)
AiService-->>ArticleService: AiSummaryResult
ArticleService-->>ArticleController: SuccessResponse
ArticleController-->>Client: AiSummaryResult
sequenceDiagram
actor User
participant ArticleWriter
participant ArticleService
participant AiService
participant TagWriter
participant ArticleRepository
participant TagRepository
participant ArticleTagRepository
User->>ArticleWriter: create(ArticleCreateRequest)
ArticleWriter->>ArticleRepository: save(article)
ArticleRepository-->>ArticleWriter: saved article
Note over ArticleWriter: 태그는 AI가<br/>생성
ArticleWriter->>AiService: generateSummaryAsync()
AiService->>AiService: buildSummaryPrompt()
AiService->>TagWriter: saveAiTags(tagNames)
TagWriter->>ArticleTagRepository: deleteByArticleId()
TagWriter->>TagRepository: findByTagName()
TagRepository-->>TagWriter: Tag or null
alt Tag 존재
TagWriter->>TagRepository: (reuse existing)
else Tag 미존재
TagWriter->>TagRepository: save(new Tag)
end
TagWriter->>ArticleTagRepository: save(ArticleTag)
TagWriter-->>AiService: done
AiService-->>ArticleWriter: done
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
- Docs: 리드미 수정 #62: Gemini API 통합 및 DTO 구조가 이 PR에서 제거/수정되었으므로, 이전 단계 작업과의 연계성이 높음
- Refacor: Notification, Tag 리팩토링 #54: 태그 처리 로직(TagWriter, ArticleTagRepository, 태그 저장 방식)이 동일하게 수정되어 직접적인 코드 레벨 관련성 있음
- Refactor(article): API 스펙 개선 및 구조 리팩토링 #56: ArticleReader, ArticleWriter, ArticleController, ArticleService 등 article 도메인의 동일 파일들이 중복 수정되어 충돌 가능성 높음
주요 검토 포인트 (코드 로직 관점)
🔴 보안 및 비즈니스 로직 관련 우려사항
-
AiService.parseAiSummaryResponse() - JSON 파싱 안정성
- Gemini API 응답 형식이 변경되면 파싱이 실패할 수 있음
- fallback으로 raw response를 summary로 사용하는데, 실제 요약 품질 보장 불가
@JsonIgnoreProperties(ignoreUnknown = true)사용했으나, 필수 필드(summary, tags) 누락 시 NPE 위험- 권장: JSON 파싱 실패 시 구체적인 에러 로깅 및 사용자에게 명확한 에러 메시지 필요
-
TagWriter.saveAiTags() - 태그 저장 로직
- 기존 ArticleTag를 모두 삭제 후 재저장하는 방식은 concurrent 요청에서 race condition 발생 가능
- 권장: 트랜잭션 격리 수준 확인, 혹은 atomic 연산으로 보장
-
ArticleReader.getTagNames() - N+1 쿼리 가능성
articleTagRepository.findAllByArticleId(articleId)호출 후 각 ArticleTag의 Tag 엔티티 접근- Tag 엔티티가 lazy loading이면 N+1 발생
- 권장: fetch join 또는
@EntityGraph사용
-
새 엔드포인트 /api/articles/summary - 입력 검증 부족
- Temp 요청에
@Valid만 있고, content 필드가 비어있거나 null인 경우 처리 미흡 - 권장: content 필드에
@NotBlank,@Size제약 추가
- Temp 요청에
-
ErrorCode enum 수정 - NOT_LOGGED_IN 제거
- 인증 관련 에러 코드가 제거되었는데, 기존 코드에서 참조하고 있는지 확인 필요
- 컴파일 오류가 없더라도 실행 시 MissingEnum 문제 발생 가능
-
GeminiService 로깅 제거
- 외부 API 호출 실패 시 로깅이 제거되어 운영 중 디버깅 어려움
- 권장: 에러 로그 유지, 혹은 응답 상태 코드만이라도 기록
🎨 태그를 AI가 그리고 ✨
요약은 JSON으로 담고 🧠
OAuth의 이름을 바꿔 🔄
더 깔끔한 API로 🚀
✨ Finishing Touches
- 📝 Generate docstrings (stacked PR)
- 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
dev
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 @coderabbitai help to get the list of available commands and usage tips.
Summary by CodeRabbit
릴리스 노트
New Features
Refactor
Chores