[FEAT]: 기수별 크루 목록 조회 API 추가 - #172
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 특정 기수에 속한 크루들의 이름, 문서 UUID, 분야 정보를 조회하는 기능을 추가합니다. 조직 문서의 소속 정보를 기반으로 데이터를 효율적으로 조회하고, 크루별로 정보를 그룹화하여 클라이언트가 필요로 하는 형태로 가공하여 제공합니다. 또한, 잘못된 요청 파라미터에 대한 검증 및 예외 처리를 강화하여 API의 안정성을 높였습니다. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new feature to query crew lists by generation, adding the /document/crews endpoint, corresponding service logic, and database queries. The review feedback highlights several critical improvement opportunities: optimizing database queries by replacing DTO projection with Fetch Join to avoid hardcoded package paths, preventing potential NullPointerExceptions in name extraction and list copying, and significantly improving test suite performance by replacing @DirtiesContext with @Transactional or manual database cleanup.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| @Override | ||
| @Query(""" | ||
| SELECT new com.wooteco.wiki.document.repository.GenerationCrewOrganizationReadModel( | ||
| crewDocument.title, | ||
| crewDocument.uuid, | ||
| organizationDocument.title | ||
| ) | ||
| FROM DocumentOrganizationLink documentOrganizationLink | ||
| JOIN documentOrganizationLink.crewDocument crewDocument | ||
| JOIN documentOrganizationLink.organizationDocument organizationDocument | ||
| WHERE crewDocument IN ( | ||
| SELECT generationLink.crewDocument | ||
| FROM DocumentOrganizationLink generationLink | ||
| WHERE generationLink.organizationDocument.title = :generationTitle | ||
| ) | ||
| """) | ||
| List<GenerationCrewOrganizationReadModel> findAllByGenerationTitle( | ||
| @Param("generationTitle") String generationTitle | ||
| ); |
There was a problem hiding this comment.
JPQL 쿼리 내에서 DTO 프로젝션(new com.wooteco.wiki.document.repository.GenerationCrewOrganizationReadModel(...))을 사용하고 있습니다. 이는 DTO의 패키지 경로를 하드코딩하게 만들어 리팩터링을 어렵게 하고 유지보수성을 떨어뜨립니다. N+1 문제를 해결하고 타입 안정성을 확보하기 위해, DTO 프로젝션 대신 Fetch Join을 사용하여 DocumentOrganizationLink 엔티티와 연관된 crewDocument, organizationDocument를 함께 조회한 후 애플리케이션 레이어에서 변환하는 방식을 권장합니다.
@Query("""
SELECT dol
FROM DocumentOrganizationLink dol
JOIN FETCH dol.crewDocument crewDocument
JOIN FETCH dol.organizationDocument organizationDocument
WHERE crewDocument IN (
SELECT generationLink.crewDocument
FROM DocumentOrganizationLink generationLink
WHERE generationLink.organizationDocument.title = :generationTitle
)
""")
List<DocumentOrganizationLink> findAllByGenerationTitle(
@Param("generationTitle") String generationTitle
);References
- To resolve N+1 query problems, prefer using a fetch join over DTO projection. DTO projection can introduce maintenance issues by hardcoding DTO package paths in JPQL queries, making refactoring difficult. Fetch join provides a type-safe alternative without this drawback.
| public Optional<String> extractName(String title) { | ||
| int delimiterIndex = title.indexOf(NAME_DELIMITER); |
There was a problem hiding this comment.
| private GenerationCrewCandidate { | ||
| organizationTitles = List.copyOf(organizationTitles); | ||
| } |
There was a problem hiding this comment.
| import org.springframework.test.annotation.DirtiesContext; | ||
|
|
There was a problem hiding this comment.
webEnvironment = SpringBootTest.WebEnvironment.NONE 환경에서 실행되는 통합 테스트이므로, 매 테스트 메서드마다 스프링 컨텍스트를 새로 띄우는 @DirtiesContext 대신 @Transactional을 사용하는 것이 좋습니다. 이를 통해 테스트 실행 속도를 획기적으로 개선할 수 있습니다.
| import org.springframework.test.annotation.DirtiesContext; | |
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) | |
| @org.springframework.transaction.annotation.Transactional |
| import org.springframework.test.annotation.DirtiesContext; | ||
|
|
||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | ||
| @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) |
There was a problem hiding this comment.
🔗 관련 이슈
📝 작업 내용
조직 문서의 소속 정보를 기준으로 크루의 이름, 문서 UUID, 분야를 조회하는 API를 추가했습니다.
주요 변경사항
GET /document/crews?generation={generation}API 추가BACKEND,FRONTEND,ANDROID분야로 변환VALIDATION_ERROR처리 추가검증 항목
null반환 검증