Skip to content

feat: 조직 문서를 조회할 때 연결된 크루 문서 목록도 함께 반환하도록 기능을 구현#157

Merged
2Jin1031 merged 2 commits intodevelopfrom
feat/156
Mar 11, 2026
Merged

feat: 조직 문서를 조회할 때 연결된 크루 문서 목록도 함께 반환하도록 기능을 구현#157
2Jin1031 merged 2 commits intodevelopfrom
feat/156

Conversation

@2Jin1031
Copy link
Collaborator

PR Summary - feat/156

📌 개요

조직 문서 조회 시 연결된 크루 문서 목록을 함께 제공하는 기능 구현

🎯 주요 변경 사항

1. 조직 문서 조회 API 응답 확장

기존 동작

  • 조직 문서 조회 시 문서 정보와 이벤트 목록만 반환
  • 해당 조직에 속한 크루원(크루 문서) 정보를 알 수 없음

개선 사항

  • 조직 문서 조회 시 연결된 크루 문서 목록도 함께 반환
  • 크루 문서의 UUID와 제목을 포함하여 응답

API 엔드포인트

GET /organization/uuid/{uuidText}

응답 예시

{
  "organizationDocumentId": 1,
  "organizationDocumentUuid": "...",
  "title": "조직 문서 제목",
  "contents": "...",
  "writer": "...",
  "generateTime": "...",
  "organizationEventResponses": [...],
  "linkedCrewDocuments": [
    {
      "documentUuid": "crew-uuid-1",
      "title": "크루원1"
    },
    {
      "documentUuid": "crew-uuid-2",
      "title": "크루원2"
    }
  ]
}

🏗️ 구현 내용

1. DTO 추가

LinkedCrewDocumentResponse.java (신규 생성)

  • 크루 문서의 핵심 정보만 담는 간단한 응답 DTO
  • 필드: documentUuid, title
  • 경량화된 응답으로 성능 최적화

2. 응답 객체 확장

OrganizationDocumentAndEventResponse.java (수정)

  • linkedCrewDocuments 필드 추가
  • 기존 생성자에 크루 문서 목록 파라미터 추가

3. Repository 메서드 추가

DocumentOrganizationLinkRepository.java (수정)

  • findAllByOrganizationDocument() 메서드 추가
  • OrganizationDocument 엔티티로 연결된 모든 링크 조회

4. Service 로직 개선

OrganizationDocumentService.java (수정)

  • findByUuid() 메서드에 크루 문서 조회 로직 추가
  • DocumentOrganizationLink를 통해 연결된 크루 문서 목록 조회
  • LinkedCrewDocumentResponse로 변환하여 응답에 포함

📁 변경된 파일

신규 추가

  • LinkedCrewDocumentResponse.java - 크루 문서 간단 응답 DTO

수정

  • OrganizationDocumentAndEventResponse.java - 크루 문서 목록 필드 추가
  • DocumentOrganizationLinkRepository.java - OrganizationDocument 기준 조회 메서드 추가
  • OrganizationDocumentService.java - 크루 문서 조회 로직 추가

🔗 관련 이슈

#156

@gemini-code-assist
Copy link

Summary of Changes

Hello, 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은 조직 문서 조회 API의 기능을 확장하여, 조직 문서와 연관된 크루 문서 목록을 함께 제공합니다. 이를 통해 클라이언트가 조직 문서와 관련된 크루 정보를 한 번의 API 호출로 얻을 수 있게 되어 데이터 접근성을 향상시키고, 추가적인 API 호출의 필요성을 줄여 사용자 경험을 개선합니다.

Highlights

  • 조직 문서 조회 API 응답 확장: 조직 문서 조회 시 연결된 크루 문서 목록을 함께 반환하도록 응답 형식이 확장되었습니다.
  • 새로운 DTO 추가: 크루 문서의 핵심 정보(UUID, 제목)를 담는 LinkedCrewDocumentResponse DTO가 새로 추가되었습니다.
  • 응답 객체 필드 추가: OrganizationDocumentAndEventResponse에 linkedCrewDocuments 필드가 추가되어 크루 문서 목록을 포함할 수 있게 되었습니다.
  • Repository 메서드 추가: DocumentOrganizationLinkRepository에 특정 조직 문서에 연결된 모든 링크를 조회하는 findAllByOrganizationDocument 메서드가 추가되었습니다.
  • Service 로직 개선: OrganizationDocumentService의 findByUuid 메서드에서 조직 문서와 연결된 크루 문서 목록을 조회하고, 이를 응답에 포함하는 로직이 구현되었습니다.
Changelog
  • src/main/java/com/wooteco/wiki/organizationdocument/dto/response/LinkedCrewDocumentResponse.java
    • 크루 문서의 UUID와 제목을 포함하는 새로운 응답 DTO가 추가되었습니다.
  • src/main/java/com/wooteco/wiki/organizationdocument/dto/response/OrganizationDocumentAndEventResponse.java
    • linkedCrewDocuments 필드가 추가되었고, 해당 필드를 포함하도록 생성자가 수정되었습니다.
  • src/main/java/com/wooteco/wiki/organizationdocument/repository/DocumentOrganizationLinkRepository.java
    • 특정 OrganizationDocument에 연결된 모든 DocumentOrganizationLink를 조회하는 findAllByOrganizationDocument 메서드가 추가되었습니다.
  • src/main/java/com/wooteco/wiki/organizationdocument/service/OrganizationDocumentService.java
    • LinkedCrewDocumentResponse와 DocumentOrganizationLinkRepository가 임포트 및 주입되었습니다.
    • findByUuid 메서드 내에서 DocumentOrganizationLinkRepository를 사용하여 조직 문서에 연결된 크루 문서 목록을 조회하고, 이를 LinkedCrewDocumentResponse로 변환하여 최종 응답에 포함하는 로직이 추가되었습니다.
Activity
  • 이 PR에 대한 기록된 활동은 없습니다.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize 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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. 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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

조직 문서 조회 시 연결된 크루 문서 목록을 함께 반환하는 기능 추가에 대한 PR 잘 보았습니다. 전반적으로 기능 구현은 잘 되었으나, 서비스 로직에서 N+1 쿼리 문제가 발생할 수 있는 부분을 발견했습니다. JPQL을 사용하여 DTO로 직접 프로젝션하는 방식으로 쿼리를 최적화하면 성능을 크게 향상시킬 수 있습니다. 관련하여 상세한 피드백을 남겼으니 확인 부탁드립니다.

Comment on lines +86 to +90
List<LinkedCrewDocumentResponse> linkedCrewDocuments = documentOrganizationLinkRepository.findAllByOrganizationDocument(
organizationDocument)
.stream()
.map(link -> new LinkedCrewDocumentResponse(link.getCrewDocument()))
.toList();

Choose a reason for hiding this comment

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

high

현재 구현은 findAllByOrganizationDocumentDocumentOrganizationLink 목록을 가져온 후, 스트림 내에서 각 link에 대해 link.getCrewDocument()를 호출하여 N+1 쿼리 문제를 발생시킬 수 있습니다. DocumentOrganizationLinkcrewDocument가 지연 로딩(LAZY)으로 설정되어 있어, 연결된 크루 문서의 수만큼 추가적인 쿼리가 발생하여 성능 저하를 유발할 수 있습니다.

이 문제를 해결하고 코드를 더 효율적으로 만들기 위해, DocumentOrganizationLinkRepository에 JPQL을 사용하여 필요한 데이터만 LinkedCrewDocumentResponse DTO로 직접 조회하는 새로운 메서드를 추가하는 것을 권장합니다. 이렇게 하면 단일 쿼리로 모든 관련 크루 문서 정보를 가져올 수 있습니다.

DocumentOrganizationLinkRepository.java에 아래와 같은 메서드를 추가할 수 있습니다:

@Query("SELECT new com.wooteco.wiki.organizationdocument.dto.response.LinkedCrewDocumentResponse(cd.uuid, cd.title) " +
       "FROM DocumentOrganizationLink dol " +
       "JOIN dol.crewDocument cd " +
       "WHERE dol.organizationDocument = :organizationDocument")
List<LinkedCrewDocumentResponse> findLinkedCrewDocumentsByOrganizationDocument(@Param("organizationDocument") OrganizationDocument organizationDocument);

그리고 서비스 로직에서는 이 새로운 메서드를 호출하도록 수정하면 됩니다.

        List<LinkedCrewDocumentResponse> linkedCrewDocuments = documentOrganizationLinkRepository.findLinkedCrewDocumentsByOrganizationDocument(organizationDocument);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

DTO Proejction을 사용하면 패키지가 쿼리 내부로 들어가기 때문에, 파일 변경 시에도 추적이 어려워질 것 같다는 우려가 들었어요. 현재로써는 사용처가 하나일 뿐이지만, 하나의 DTO 패키지의 하드코딩 방식이 어려 메서드에 분산되어 있다면 유지보수 측면에서 비용이 더욱 늘거라고 생각하고요.

현재 문제점으로 제안해주신 부분이 N+1인 만큼, 이 부분은 성능 상 고려해야 할 점이라는 생각이 들어서
다음과 같은 방법을 고려해봤습니다.
"repository에서의 fetch join"

이 방식을 사용하게 되면 N+1문제도 해결하면서 런타임 환경에서의 타입 안정성도 확인할 수 있을 것 같아서요!
혹시 이 방식은 어떻게 생각하시는 지 궁금합니다.
아래 코드를 함께 남겨 놓도록 할게요!

@Query("SELECT documentOrganizationLink FROM DocumentOrganizationLink documentOrganizationLink " +
            "JOIN FETCH documentOrganizationLink.crewDocument " +
            "WHERE documentOrganizationLink.organizationDocument = :organizationDocument")
    List<DocumentOrganizationLink> findAllByOrganizationDocumentWithCrewDocument(
            @Param("organizationDocument") OrganizationDocument organizationDocument);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

/gemini review

Choose a reason for hiding this comment

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

2Jin1031님, DTO Projection 사용 시 패키지 변경 추적의 어려움에 대한 우려는 충분히 이해합니다. 특히 DTO 구조가 자주 변경되거나 여러 곳에서 사용될 경우 유지보수 비용이 증가할 수 있습니다.

제안해주신 FETCH JOIN 방식은 N+1 문제를 해결하면서 런타임 시 타입 안정성을 유지하는 아주 좋은 대안입니다. FETCH JOIN을 사용하면 DocumentOrganizationLink 엔티티를 조회할 때 연관된 crewDocument를 즉시 로딩하여 N+1 쿼리를 방지할 수 있습니다. 이 방식은 DTO Projection과 달리 Repository 계층에서 DTO 패키지 경로를 직접 참조하지 않으므로, DTO 변경에 따른 Repository 코드 수정 부담을 줄일 수 있습니다.

다만, FETCH JOIN은 경우에 따라 불필요하게 많은 데이터를 가져올 수 있지만, 현재 DocumentOrganizationLinkCrewDocument의 관계에서는 큰 문제가 되지 않을 것으로 보입니다.

제안해주신 findAllByOrganizationDocumentWithCrewDocument 메서드를 DocumentOrganizationLinkRepository에 추가하고, OrganizationDocumentService에서는 이 메서드를 호출하도록 수정하면 N+1 문제를 효과적으로 해결할 수 있습니다.

DocumentOrganizationLinkRepository.java에 다음 메서드를 추가해주세요:

@Query("SELECT dol FROM DocumentOrganizationLink dol JOIN FETCH dol.crewDocument WHERE dol.organizationDocument = :organizationDocument")
List<DocumentOrganizationLink> findAllByOrganizationDocumentWithCrewDocument(@Param("organizationDocument") OrganizationDocument organizationDocument);

그리고 OrganizationDocumentService.java의 해당 부분을 다음과 같이 수정할 수 있습니다. 이 변경은 기존 findAllByOrganizationDocument 호출을 새로운 FETCH JOIN 메서드 호출로 대체하여 N+1 문제를 해결합니다.

Suggested change
List<LinkedCrewDocumentResponse> linkedCrewDocuments = documentOrganizationLinkRepository.findAllByOrganizationDocument(
organizationDocument)
.stream()
.map(link -> new LinkedCrewDocumentResponse(link.getCrewDocument()))
.toList();
List<LinkedCrewDocumentResponse> linkedCrewDocuments = documentOrganizationLinkRepository.findAllByOrganizationDocumentWithCrewDocument(
organizationDocument)
.stream()
.map(link -> new LinkedCrewDocumentResponse(link.getCrewDocument()))
.toList();

Copy link
Member

@CheChe903 CheChe903 left a comment

Choose a reason for hiding this comment

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

어푸~ 재민이 코멘트만 확인 부탁합니당~

@2Jin1031 2Jin1031 closed this Mar 11, 2026
@2Jin1031 2Jin1031 reopened this Mar 11, 2026
@2Jin1031 2Jin1031 merged commit 288fc73 into develop Mar 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants