Skip to content

Feat/#89 현재 워크스페이스 설정 및 조회 구현#103

Merged
jinnieusLab merged 10 commits intodevelopfrom
feat/#89
Mar 28, 2026
Merged

Feat/#89 현재 워크스페이스 설정 및 조회 구현#103
jinnieusLab merged 10 commits intodevelopfrom
feat/#89

Conversation

@jinnieusLab
Copy link
Copy Markdown
Collaborator

@jinnieusLab jinnieusLab commented Mar 27, 2026

📌 관련 이슈

🚀 개요

유저의 현재 워크스페이스를 설정하고 이를 조회할 수 있는 API를 구현하였습니다. 또한 조직 목록 조회 시 워크스페이스 설정 여부를 함께 반환하도록 하였습니다.

📄 작업 내용

  • User에 currentOrgId 필드 추가

  • 현재 워크스페이스 설정 POST api/org/{orgId}/workspace
    : 요청으로 전달 받은 orgId를 유저의 현재 워크스페이스로 설정

  • 현재 워크스페이스 조회 GET api/org/my/workspace
    : 유저의 현재 워크스페이스로 설정된 조직 id를 반환

  • 내 워크스페이스 목록 전체 조회 GET /api/org/my에서 응답 수정
    : 워크스페이스 설정 여부를 함께 반환

📸 스크린샷 / 테스트 결과 (선택)

프론트의 워크스페이스 선택 화면 구현 시 활용될 수 있도록, 내 워크스페이스 목록을 전체 조회할 시 다음과 같이 isCurrentWorkspace의 값을 함께 조직 정보(SimpleInfo)에 반환하여, 현재 워크스페이스로 설정된 조직이 무엇인지 확인할 수 있게 함.
image

✅ 체크리스트

  • 브랜치 전략(GitHub Flow)을 준수했나요?
  • 메서드 단위로 코드가 잘 쪼개져 있나요?
  • 테스트 통과 확인
  • 서버 실행 확인
  • API 동작 확인

🔍 리뷰 포인트 (Review Points)

워크스페이스 설정 및 조회 api의 응답을 우선 orgId만 반환하도록 하였는데, 더 자세하게 조직의 정보까지 포함하는 게 좋을지 고민이네요.. 또 기타 수정해야할 사항이 있다면 조언 부탁드리겠습니다!

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

  • 새로운 기능
    • 현재 작업 공간(활성 워크스페이스)을 설정하고 조회하는 기능이 추가되었습니다.
    • 조직 목록에서 각 조직이 현재 작업 공간인지 표시되어 한눈에 확인할 수 있습니다.
  • 동작 개선
    • 작업 공간 변경 및 조직/멤버 제거 시 사용자의 현재 작업 공간이 자동으로 반영 및 초기화됩니다.
  • 문서
    • 관련 API 문서와 조직 조회 설명에 현재 작업 공간 정보가 추가되었습니다.

@jinnieusLab jinnieusLab self-assigned this Mar 27, 2026
@jinnieusLab jinnieusLab added the ✨ Feature 새로운 기능 추가 label Mar 27, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

Walkthrough

사용자별 현재 워크스페이스를 설정·조회하는 API와 관련 DTO/엔티티/로직을 추가합니다. User 엔티티에 currentOrgId를 도입하고, 컨버터/서비스/컨트롤러에서 이를 전달·관리하며 조직 삭제/멤버 제거 시 해당 필드를 초기화합니다.

Changes

Cohort / File(s) Summary
응답 DTO 및 변환 로직
src/main/java/com/whereyouad/WhereYouAd/domains/organization/application/dto/response/OrgResponse.java, src/main/java/com/whereyouad/WhereYouAd/domains/organization/application/mapper/OrgConverter.java
OrgResponse.SimpleInfoisCurrentWorkspace boolean 필드 추가. 새 OrgResponse.CurrentWorkspace(Long orgId) 레코드 추가. OrgConverter.toOrgSimpleInfo 오버로드로 currentOrgId 전달해 현재 워크스페이스 여부를 설정.
서비스 계층
src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgService.java, src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java
인터페이스에 setCurrentWorkspace(Long userId, Long orgId)getCurrentWorkspace(Long userId) 추가. 구현체에서 사용자 로드 후 currentOrgId를 읽어 변환에 전달. 워크스페이스 설정/조회 로직 추가. 조직 삭제(하드/소프트) 및 멤버 제거 시 관련 사용자의 currentOrgId를 null로 초기화.
컨트롤러 및 API 문서
src/main/java/com/whereyouad/WhereYouAd/domains/organization/presentation/OrgController.java, src/main/java/com/whereyouad/WhereYouAd/domains/organization/presentation/docs/OrgControllerDocs.java
POST /api/org/{orgId}/workspace(set) 및 GET /api/org/my/workspace(get) 엔드포인트 추가. API 문서에 응답/에러 코드 및 getMyOrganizations 설명에 현재 워크스페이스 필드 반영.
사용자 엔티티
src/main/java/com/whereyouad/WhereYouAd/domains/user/persistence/entity/User.java
currentOrgId JPA 필드(current_org_id) 추가 및 setCurrentOrgId 세터 추가.
리포지토리 쿼리(fetch 전략 변경)
src/main/java/com/whereyouad/WhereYouAd/domains/organization/persistence/repository/OrgMemberRepository.java
findOrgMemberByOrg JPQL을 join fetch om.user로 변경해 OrgMember와 연관된 User를 즉시 페치하도록 수정.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller as OrgController
    participant Service as OrgService
    participant UserRepo as UserRepository
    participant OrgMemberRepo as OrgMemberRepository
    participant DB as Database

    rect rgba(100, 150, 200, 0.5)
    Note over Client,DB: setCurrentWorkspace - 현재 워크스페이스 설정
    Client->>Controller: POST /api/org/{orgId}/workspace (userId, orgId)
    Controller->>Service: setCurrentWorkspace(userId, orgId)
    Service->>UserRepo: findById(userId)
    UserRepo->>DB: SELECT * FROM users
    DB-->>UserRepo: User
    UserRepo-->>Service: User
    Service->>OrgMemberRepo: findByOrgIdAndUserId(orgId, userId)
    OrgMemberRepo->>DB: SELECT * FROM org_members
    DB-->>OrgMemberRepo: OrgMember
    OrgMemberRepo-->>Service: OrgMember
    Service->>DB: UPDATE users SET current_org_id = ?
    Service-->>Controller: CurrentWorkspace(orgId)
    Controller-->>Client: DataResponse<CurrentWorkspace>
    end

    rect rgba(150, 100, 200, 0.5)
    Note over Client,DB: getCurrentWorkspace - 현재 워크스페이스 조회
    Client->>Controller: GET /api/org/my/workspace (userId)
    Controller->>Service: getCurrentWorkspace(userId)
    Service->>UserRepo: findById(userId)
    UserRepo->>DB: SELECT current_org_id FROM users
    DB-->>UserRepo: User(currentOrgId)
    UserRepo-->>Service: User
    Service-->>Controller: CurrentWorkspace(currentOrgId)
    Controller-->>Client: DataResponse<CurrentWorkspace>
    end

    rect rgba(200, 150, 100, 0.5)
    Note over Client,DB: getMyOrganizations - 워크스페이스 목록 조회 (변경)
    Client->>Controller: GET /api/org/my (userId)
    Controller->>Service: getMyOrganizations(userId)
    Service->>UserRepo: findById(userId)
    UserRepo->>DB: SELECT current_org_id FROM users
    DB-->>UserRepo: User(currentOrgId)
    UserRepo-->>Service: User
    Service->>OrgMemberRepo: findByUserId(userId)
    OrgMemberRepo->>DB: SELECT * FROM org_members
    DB-->>OrgMemberRepo: List<OrgMember>
    OrgMemberRepo-->>Service: OrgMembers
    Service->>Service: toOrgSimpleInfo(orgMember, currentOrgId) (for each)
    Service-->>Controller: MyOrganizations(List<SimpleInfo>)
    Controller-->>Client: DataResponse<MyOrganizations>
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • kingmingyu
  • ojy0903
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 핵심 변경사항을 명확하게 설명합니다. '현재 워크스페이스 설정 및 조회 구현'은 추가된 기능을 구체적으로 나타냅니다.
Description check ✅ Passed PR 설명이 템플릿의 주요 섹션(관련 이슈, 개요, 작업 내용, 스크린샷, 체크리스트, 리뷰 포인트)을 모두 포함하고 있습니다. 작업 내용이 구체적이고 API 엔드포인트까지 명시되어 있습니다.
Linked Issues check ✅ Passed PR의 모든 변경사항이 이슈 #89의 목표(현재 워크스페이스 설정/조회 API 구현)를 충족합니다. 설정 API, 조회 API, 목록 조회 응답 수정이 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 현재 워크스페이스 기능 구현에 직접 관련되어 있습니다. User 엔티티 필드 추가, 서비스/컨트롤러 확장, 응답 DTO 수정이 모두 해당 기능 범위 내입니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#89

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`:
- Around line 111-133: The current setCurrentWorkSpace and getCurrentWorkSpace
allow stale/soft-deleted orgs to be set or returned; update setCurrentWorkSpace
to verify the target org is active (not soft-deleted) and the membership is
active before assigning (use OrgRepository to load org by id and check its
active/deleted flag and use OrgMemberRepository to ensure active membership),
then persist the user (userRepository.save(user)) after
user.setCurrentOrgId(orgId); update getCurrentWorkSpace to validate
user.getCurrentOrgId() by loading the Org and membership similarly, and if
invalid clear user.setCurrentOrgId(null), persist the user, and throw
OrgHandler(OrgErrorCode.CURRENT_WORKSPACE_NOT_SET) (or return a not-set
response) so the API no longer returns stale workspaces; reference methods:
setCurrentWorkSpace, getCurrentWorkSpace,
OrgMemberRepository.findByUserIdAndOrgId (replace/extend with an
active-membership check), and the OrgRepository load/check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0261e946-ef14-48a9-8b67-13815b3e3656

📥 Commits

Reviewing files that changed from the base of the PR and between e1d977f and 3293df1.

📒 Files selected for processing (8)
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/application/dto/response/OrgResponse.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/application/mapper/OrgConverter.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgService.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/exception/code/OrgErrorCode.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/presentation/OrgController.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/presentation/docs/OrgControllerDocs.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/user/persistence/entity/User.java

Copy link
Copy Markdown
Collaborator

@ojy0903 ojy0903 left a comment

Choose a reason for hiding this comment

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

P4: 고생하셨습니다! 처음에 현재 워크스페이스 어떤 것을 보고있는지 반환하는 로직을 생각했을 때 구현 방법이 막연했었는데 User 에 currentOrgid 를 넣어서 진행하는 방식이 간단하게 구현 가능해서 좋은 것 같습니다. 내 워크스페이스 목록 조회에서 isCurrentWorkSpace 필드를 넣어서 현재 설정 조직 나타내는 것도 좋은 것 같아요!!

응답값은 제 생각에는 워크스페이스 설정/조회 API 에서 orgid 만 반환해도 깔끔해서 괜찮은 것 같긴 합니다.... 좀 더 추가해야 할 것 같다면 message 필드 정도 어떨까요? 워크스페이스 설징 시에는 message 를 "현재 워크스페이스를 orgId=" + orgId + " 로 설정했습니다." 로 하고, 조회 시에는 message 를 "현재 설정된 워크스페이스는 orgId=" + orgId + " 입니다." 로 하는 것도 괜찮을 것 같습니다...! 필수적이진 않을 것 같아서 선택사항으로 해도 될거 같아요...!!

Copy link
Copy Markdown

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

♻️ Duplicate comments (2)
src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java (2)

110-121: ⚠️ Potential issue | 🟠 Major

Soft-delete된 조직도 현재 워크스페이스로 설정될 수 있습니다.

findByUserIdAndOrgId는 조직의 status를 확인하지 않아서, 이미 삭제된(soft-deleted) 조직도 현재 워크스페이스로 설정될 수 있어요. 예를 들어 org A가 soft-delete 상태인데도 사용자가 이를 현재 워크스페이스로 설정할 수 있습니다.

조직 상태가 ACTIVE인지 추가로 검증하거나, repository 메서드에 상태 조건을 추가해주세요.

🛠️ 수정 제안
 `@Override`
 public OrgResponse.CurrentWorkspace setCurrentWorkspace(Long userId, Long orgId) {
     User user = userRepository.findById(userId).orElseThrow(() ->
             new UserHandler(UserErrorCode.USER_NOT_FOUND));

-    orgMemberRepository.findByUserIdAndOrgId(userId, orgId).orElseThrow(() ->
-            new OrgHandler(OrgErrorCode.ORG_MEMBER_NOT_FOUND));
+    OrgMember orgMember = orgMemberRepository.findByUserIdAndOrgId(userId, orgId).orElseThrow(() ->
+            new OrgHandler(OrgErrorCode.ORG_MEMBER_NOT_FOUND));
+
+    // 조직이 ACTIVE 상태인지 검증
+    if (orgMember.getOrganization().getStatus() != OrgStatus.ACTIVE) {
+        throw new OrgHandler(OrgErrorCode.ORG_SOFT_DELETED);
+    }

     user.setCurrentOrgId(orgId);

     return new OrgResponse.CurrentWorkspace(orgId);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`
around lines 110 - 121, setCurrentWorkspace currently trusts
orgMemberRepository.findByUserIdAndOrgId without validating the organization's
status, allowing soft-deleted orgs to be set as current; fix by ensuring the org
is ACTIVE before assigning: fetch the Org entity (via orgRepository.findById or
by adding a repository method like findByUserIdAndOrgIdAndOrgStatus), verify
org.getStatus() == ACTIVE, and if not throw an OrgHandler with an appropriate
OrgErrorCode (e.g., ORG_NOT_ACTIVE or a new error), only then call
user.setCurrentOrgId(orgId) and return new OrgResponse.CurrentWorkspace(orgId).

123-134: ⚠️ Potential issue | 🟠 Major

Stale한 currentOrgId가 그대로 반환될 수 있습니다.

사용자가 조직에서 제거되거나 조직이 삭제된 후에도 currentOrgId가 정리되지 않으면, 이 API는 더 이상 유효하지 않은 조직 ID를 반환하게 됩니다.

예시 시나리오:

  1. 사용자가 org A를 현재 워크스페이스로 설정
  2. 관리자가 org A에서 해당 사용자를 제거
  3. /api/org/my에는 org A가 없지만, /api/org/my/workspace는 org A의 ID를 반환 → 데이터 불일치

조회 시에도 현재 멤버십과 조직 활성 상태를 검증하거나, 조직 삭제/멤버 제거 시 currentOrgId를 정리하는 로직이 필요합니다.

🛠️ 수정 제안 (조회 시 검증 방식)
 `@Override`
 public OrgResponse.CurrentWorkspace getCurrentWorkspace(Long userId) {
     User user = userRepository.findById(userId).orElseThrow(() ->
             new UserHandler(UserErrorCode.USER_NOT_FOUND));

     Long currentOrgId = user.getCurrentOrgId();

     if (currentOrgId == null)
         throw new OrgHandler(OrgErrorCode.CURRENT_WORKSPACE_NOT_SET);

+    // 현재 워크스페이스가 여전히 유효한지 검증
+    OrgMember orgMember = orgMemberRepository.findByUserIdAndOrgId(userId, currentOrgId)
+            .orElse(null);
+
+    if (orgMember == null || orgMember.getOrganization().getStatus() != OrgStatus.ACTIVE) {
+        // 유효하지 않으면 currentOrgId 초기화
+        user.setCurrentOrgId(null);
+        throw new OrgHandler(OrgErrorCode.CURRENT_WORKSPACE_NOT_SET);
+    }

     return new OrgResponse.CurrentWorkspace(currentOrgId);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`
around lines 123 - 134, In getCurrentWorkspace(Long userId) validate that the
stored currentOrgId is still valid: after loading User via
userRepository.findById, if user.getCurrentOrgId() != null then load the Org
using orgRepository.findById(currentOrgId) and check the org is present and
active (e.g., not deleted) and that the user is still a member using
membershipRepository.existsByUserIdAndOrgId(userId, currentOrgId); if any check
fails, clear the stale value by calling user.setCurrentOrgId(null) and
userRepository.save(user), then throw the same
OrgHandler(OrgErrorCode.CURRENT_WORKSPACE_NOT_SET) (or return an appropriate
empty response) instead of returning the stale ID so the API never returns an
invalid workspace id.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`:
- Around line 110-121: setCurrentWorkspace currently trusts
orgMemberRepository.findByUserIdAndOrgId without validating the organization's
status, allowing soft-deleted orgs to be set as current; fix by ensuring the org
is ACTIVE before assigning: fetch the Org entity (via orgRepository.findById or
by adding a repository method like findByUserIdAndOrgIdAndOrgStatus), verify
org.getStatus() == ACTIVE, and if not throw an OrgHandler with an appropriate
OrgErrorCode (e.g., ORG_NOT_ACTIVE or a new error), only then call
user.setCurrentOrgId(orgId) and return new OrgResponse.CurrentWorkspace(orgId).
- Around line 123-134: In getCurrentWorkspace(Long userId) validate that the
stored currentOrgId is still valid: after loading User via
userRepository.findById, if user.getCurrentOrgId() != null then load the Org
using orgRepository.findById(currentOrgId) and check the org is present and
active (e.g., not deleted) and that the user is still a member using
membershipRepository.existsByUserIdAndOrgId(userId, currentOrgId); if any check
fails, clear the stale value by calling user.setCurrentOrgId(null) and
userRepository.save(user), then throw the same
OrgHandler(OrgErrorCode.CURRENT_WORKSPACE_NOT_SET) (or return an appropriate
empty response) instead of returning the stale ID so the API never returns an
invalid workspace id.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2794c374-e5a7-443b-97c1-902c5e93bdb6

📥 Commits

Reviewing files that changed from the base of the PR and between 3293df1 and dd3a0eb.

📒 Files selected for processing (5)
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/application/dto/response/OrgResponse.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgService.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/presentation/OrgController.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/presentation/docs/OrgControllerDocs.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgService.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/application/dto/response/OrgResponse.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/presentation/docs/OrgControllerDocs.java

Copy link
Copy Markdown
Collaborator

@kingmingyu kingmingyu left a comment

Choose a reason for hiding this comment

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

P4: 고생하셨습니다! user에 필드 값을 추가해서 깔끔하게 구현해주신 것 같습니다! orgId만 반환해도 괜찮을 것 같습니다!
저희 그럼 조직 맴버 삭제나 조직 삭제 시에도 관련 유저에 대한 currentOrgId값들을 null 값으로 만들어주는 리펙터링을 따로 진행해야 한다고 이해했는데 이 방향이 맞을까요?

@jinnieusLab
Copy link
Copy Markdown
Collaborator Author

남겨주신 피드백 바탕으로 현재 워크스페이스 조회 시 null이어도 에러 처리 없이 응답하도록 변경하고, 조직이나 조직 멤버가 삭제, 추방될 시에는 해당되는 유저들이나 유저의 currentOrgId가 null로 설정되도록 반영하였습니다!

Copy link
Copy Markdown

@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

♻️ Duplicate comments (1)
src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java (1)

110-121: ⚠️ Potential issue | 🟠 Major

Soft Delete된 조직을 현재 워크스페이스로 설정할 수 있습니다.

findByUserIdAndOrgId 쿼리가 사용자 상태만 검증하고 조직의 상태는 검증하지 않아서, 이미 삭제된(DELETED 상태인) 조직도 현재 워크스페이스로 설정될 수 있습니다. 예를 들어 조직 A를 soft delete한 후에도 이 메서드로 해당 조직을 워크스페이스로 지정할 수 있다는 뜻이에요.

조직 상태가 ACTIVE인지 추가로 검증하세요.

제안하는 수정 방법

쿼리 레벨에서 조직 상태를 필터링하거나, 메서드에서 반환된 OrgMember의 조직 상태를 확인하세요:

 `@Override`
 public OrgResponse.CurrentWorkspace setCurrentWorkspace(Long userId, Long orgId) {
     User user = userRepository.findById(userId).orElseThrow(() ->
             new UserHandler(UserErrorCode.USER_NOT_FOUND));

-    orgMemberRepository.findByUserIdAndOrgId(userId, orgId).orElseThrow(() ->
-            new OrgHandler(OrgErrorCode.ORG_MEMBER_NOT_FOUND));
+    OrgMember orgMember = orgMemberRepository.findByUserIdAndOrgId(userId, orgId)
+            .orElseThrow(() -> new OrgHandler(OrgErrorCode.ORG_MEMBER_NOT_FOUND));
+
+    if (orgMember.getOrganization().getStatus() == OrgStatus.DELETED) {
+        throw new OrgHandler(OrgErrorCode.ORG_SOFT_DELETED);
+    }

     user.setCurrentOrgId(orgId);

     return new OrgResponse.CurrentWorkspace(orgId);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`
around lines 110 - 121, The setCurrentWorkspace method in OrgServiceImpl allows
a soft-deleted org to be set as the current workspace because
orgMemberRepository.findByUserIdAndOrgId(...) does not verify the org's status;
update the logic to ensure the organization is ACTIVE before setting
currentOrgId: either extend the orgMemberRepository query to filter by
org.status = ACTIVE (e.g., a findByUserIdAndOrgIdAndOrgStatus...) or after
fetching the OrgMember load the associated Org and throw
OrgHandler(OrgErrorCode.ORG_NOT_ACTIVE) if org.getStatus() != OrgStatus.ACTIVE;
keep userRepository.findById(...) check and only call
user.setCurrentOrgId(orgId) when the org status is validated.
🧹 Nitpick comments (1)
src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java (1)

289-295: 위와 동일한 N+1 쿼리 개선 기회가 있습니다.

Hard Delete 로직과 마찬가지로, 여기서도 findOrgMemberByOrgWithUser 같은 fetch join 메서드를 사용하면 쿼리 효율성을 높일 수 있어요. Soft Delete가 Hard Delete보다 더 자주 호출될 수 있으므로 최적화 효과가 클 수 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`
around lines 289 - 295, The loop in OrgServiceImpl uses
orgMemberRepository.findOrgMemberByOrg which triggers N+1 when accessing
member.getUser(); replace the call with a fetch-join repository method (e.g.,
findOrgMemberByOrgWithUser) that loads OrgMember together with User to avoid
lazy loads, then iterate the returned list to null out currentOrgId as before
and ensure changes are flushed/persisted (saveAll or rely on transactional
flush) so updates are applied; update the repository usage from
findOrgMemberByOrg to findOrgMemberByOrgWithUser in OrgServiceImpl.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`:
- Around line 255-260: The loop in OrgServiceImpl that iterates orgMembers (and
the similar loop in removeOrganizationSoft) triggers an N+1 because the
repository method findOrgMemberByOrg does not fetch-join User; update the
repository to provide a fetch-join variant (e.g., modify findOrgMemberByOrg
query to include JOIN FETCH m.user or add a new method like
findOrgMemberByOrgWithUser) and then use that fetch-join method in
OrgServiceImpl where you set member.getUser().setCurrentOrgId(null) so
member.getUser() is loaded in one query; apply the same change for the
repository call used by removeOrganizationSoft to eliminate its N+1 as well.

---

Duplicate comments:
In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`:
- Around line 110-121: The setCurrentWorkspace method in OrgServiceImpl allows a
soft-deleted org to be set as the current workspace because
orgMemberRepository.findByUserIdAndOrgId(...) does not verify the org's status;
update the logic to ensure the organization is ACTIVE before setting
currentOrgId: either extend the orgMemberRepository query to filter by
org.status = ACTIVE (e.g., a findByUserIdAndOrgIdAndOrgStatus...) or after
fetching the OrgMember load the associated Org and throw
OrgHandler(OrgErrorCode.ORG_NOT_ACTIVE) if org.getStatus() != OrgStatus.ACTIVE;
keep userRepository.findById(...) check and only call
user.setCurrentOrgId(orgId) when the org status is validated.

---

Nitpick comments:
In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java`:
- Around line 289-295: The loop in OrgServiceImpl uses
orgMemberRepository.findOrgMemberByOrg which triggers N+1 when accessing
member.getUser(); replace the call with a fetch-join repository method (e.g.,
findOrgMemberByOrgWithUser) that loads OrgMember together with User to avoid
lazy loads, then iterate the returned list to null out currentOrgId as before
and ensure changes are flushed/persisted (saveAll or rely on transactional
flush) so updates are applied; update the repository usage from
findOrgMemberByOrg to findOrgMemberByOrgWithUser in OrgServiceImpl.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 21b73139-5c1c-4767-8279-8387ec7ea288

📥 Commits

Reviewing files that changed from the base of the PR and between dd3a0eb and a3e7198.

📒 Files selected for processing (1)
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/domain/service/OrgServiceImpl.java

Copy link
Copy Markdown

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

🧹 Nitpick comments (2)
src/main/java/com/whereyouad/WhereYouAd/domains/organization/persistence/repository/OrgMemberRepository.java (2)

65-65: 들여쓰기 일관성 확인 필요 (Nitpick)

이 줄의 들여쓰기가 다른 메서드 선언들과 다르게 보여요. 인터페이스 레벨의 다른 메서드들은 4칸 들여쓰기를 사용하는데, 이 줄은 8칸으로 되어 있네요.

💅 들여쓰기 정렬 제안
-        Boolean existsByUserAndOrganization(User user, Organization organization);
+    Boolean existsByUserAndOrganization(User user, Organization organization);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/persistence/repository/OrgMemberRepository.java`
at line 65, Fix indentation inconsistency in the OrgMemberRepository interface:
align the method declaration Boolean existsByUserAndOrganization(User user,
Organization organization); to use the same 4-space indentation as the other
interface methods so it matches the surrounding method declarations and code
style.

49-53: 관련 연관 엔티티 접근 시 추가 쿼리 가능성 (참고)

이 메서드는 Optional<OrgMember>를 반환하면서 organization이나 user에 대한 fetch join이 없어요. 호출하는 쪽에서 이 연관 엔티티들에 접근한다면 추가 쿼리가 발생할 수 있습니다.

단일 엔티티 반환이라 N+1 문제의 심각도는 낮지만, 만약 이 메서드를 사용하는 서비스에서 OrgMemberorganization 정보에도 접근한다면 fetch join 추가를 고려해볼 수 있어요.

현재 변경 범위 밖이므로 참고 사항으로 남겨둡니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/persistence/repository/OrgMemberRepository.java`
around lines 49 - 53, The custom query in
OrgMemberRepository.findByUserIdAndOrgId returns Optional<OrgMember> without
fetch joins, so accessing related entities (OrgMember.organization or
OrgMember.user) later may trigger extra lazy-load queries; to fix, update the
query to include fetch joins for the needed associations (e.g., add "JOIN FETCH
om.organization" and/or "JOIN FETCH om.user") when callers require those
relationships, or create a separate repository method (e.g.,
findByUserIdAndOrgIdWithRelations) that uses fetch joins so callers that need
organization/user avoid additional queries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@src/main/java/com/whereyouad/WhereYouAd/domains/organization/persistence/repository/OrgMemberRepository.java`:
- Line 65: Fix indentation inconsistency in the OrgMemberRepository interface:
align the method declaration Boolean existsByUserAndOrganization(User user,
Organization organization); to use the same 4-space indentation as the other
interface methods so it matches the surrounding method declarations and code
style.
- Around line 49-53: The custom query in
OrgMemberRepository.findByUserIdAndOrgId returns Optional<OrgMember> without
fetch joins, so accessing related entities (OrgMember.organization or
OrgMember.user) later may trigger extra lazy-load queries; to fix, update the
query to include fetch joins for the needed associations (e.g., add "JOIN FETCH
om.organization" and/or "JOIN FETCH om.user") when callers require those
relationships, or create a separate repository method (e.g.,
findByUserIdAndOrgIdWithRelations) that uses fetch joins so callers that need
organization/user avoid additional queries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c4b2e4e7-b570-4baa-b46e-48e95f2846da

📥 Commits

Reviewing files that changed from the base of the PR and between a3e7198 and 1247c23.

📒 Files selected for processing (1)
  • src/main/java/com/whereyouad/WhereYouAd/domains/organization/persistence/repository/OrgMemberRepository.java

@jinnieusLab jinnieusLab merged commit 2fb9654 into develop Mar 28, 2026
2 checks passed
@jinnieusLab jinnieusLab deleted the feat/#89 branch March 28, 2026 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 워크스페이스 선택 API 구현

3 participants