Skip to content

[FEAT] 회원탈퇴 API 개발#87

Merged
Be-HinD merged 3 commits intomainfrom
feat/withdraw
Dec 11, 2025
Merged

[FEAT] 회원탈퇴 API 개발#87
Be-HinD merged 3 commits intomainfrom
feat/withdraw

Conversation

@Be-HinD
Copy link
Member

@Be-HinD Be-HinD commented Dec 11, 2025

📝 Pull Request

📌 PR 종류

해당하는 항목에 체크해주세요.

  • 기능 추가 (Feature)
  • 버그 수정 (Fix)
  • 문서 수정 (Docs)
  • 코드 리팩터링 (Refactor)
  • 테스트 추가 (Test)
  • 기타 변경 (Chore)

✨ 변경 내용

회원탈퇴 API 개발
v1 팔로우 등록/취소 관련 카운트 업데이트 로직 추가


🔍 관련 이슈

해당 PR이 해결하는 이슈가 있다면 연결해주세요.
Closes #59


🧪 테스트

변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.

  • 유닛 테스트 추가 / 수정
  • 통합 테스트 검증
  • 수동 테스트 완료

🚨 확인해야 할 사항 (Checklist)

PR을 제출하기 전에 아래 항목들을 확인해주세요.

  • 코드 포매팅 완료
  • 불필요한 파일/코드 제거
  • 로직 검증 완료
  • 프로젝트 빌드 성공
  • 린트/정적 분석 통과 (해당 시)

🙋 기타 참고 사항

  • RefreshToken redis 블랙리스트 관리 로직 추가 시 회원탈퇴 로직 일부 수정 필요

Summary by CodeRabbit

  • 새로운 기능

    • 계정 탈퇴 기능 추가: 인증된 사용자가 계정 탈퇴 시 처리되며 관련 보안 쿠키가 제거됩니다.
  • 개선사항

    • 팔로우/언팔로우 시 팔로워·팔로우잉 카운트가 즉시 업데이트됩니다.
    • 언팔로우 API 응답 상태 코드를 201에서 200으로 표준화했습니다.
    • 공개 인증 엔드포인트 범위를 signup/login/refresh로 명시하여 접근 범위를 정교화했습니다.

✏️ Tip: You can customize this high-level summary in your review settings.

@Be-HinD Be-HinD self-assigned this Dec 11, 2025
@Be-HinD Be-HinD added the ✨enhancement New feature or request label Dec 11, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 11, 2025

Walkthrough

회원탈퇴(soft-delete) 엔드포인트와 서비스 로직을 추가하고, 리프레시 토큰 쿠키 삭제 로직을 공통 헬퍼로 분리했으며, 팔로우 생성/삭제 시 팔로우 카운터를 동기화하고 언팔로우 응답 코드를 201→200으로 변경했습니다.

Changes

Cohort / File(s) Summary
회원탈퇴 API 구현
src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java, src/main/java/team/wego/wegobackend/auth/presentation/AuthControllerDocs.java, src/main/java/team/wego/wegobackend/auth/application/AuthService.java
DELETE /withdraw 엔드포인트 추가(인증 필요). AuthController에 쿠키 삭제용 deleteRefreshTokenCookie(HttpServletResponse) 헬퍼 추가 및 로그아웃에서 재사용. AuthService에 withDraw(Long userId) 추가하여 사용자 조회 후 소프트 삭제(updatedeleted(true)) 수행.
사용자 삭제 플래그 관리
src/main/java/team/wego/wegobackend/user/domain/User.java
사용자 엔티티에 public void updatedeleted(Boolean flag) 메서드 추가(soft-delete 플래그 설정).
팔로우 카운터 업데이트
src/main/java/team/wego/wegobackend/user/application/FollowService.java
팔로우 생성 시 follower/ followee 카운터 증가 호출(increaseFolloweeCount() / increaseFollowerCount()), 언팔로우 시 감소 호출(decreaseFolloweeCount() / decreaseFollowerCount()) 추가.
팔로우 취소 응답 개선
src/main/java/team/wego/wegobackend/user/presentation/UserController.java
언팔로우 응답 HTTP 상태를 201 Created에서 200 OK로 변경하고 관련 TODO 주석 제거.
보안 엔드포인트 범위 조정
src/main/java/team/wego/wegobackend/common/security/SecurityEndpoints.java
공개 패턴에서 "/api/v*/auth/**" 와일드카드 제거, 대신 "/api/v*/auth/signup", "/api/v*/auth/login", "/api/v*/auth/refresh" 명시적으로 추가.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • AuthService.withDraw: 사용자 조회 예외 처리와 트랜잭션/영속성 경계 확인 필요
  • deleteRefreshTokenCookie 재사용성 및 쿠키 속성(도메인, 경로, Secure/HttpOnly) 검토
  • FollowService 카운터 업데이트: 동시성(경합) 및 트랜잭션 일관성 확인

Possibly related PRs

Poem

🐰 작별 인사 살포시 남기고,
쿠키는 바람에 흩어지고,
삭제 플래그로 조용히 안녕을,
카운터는 맞춰 한숨 놓고,
토끼는 깡충, 코드 리뷰로 축하해요 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning FollowService의 팔로우/언팔로우 카운터 업데이트와 UserController의 언팔로우 HTTP 상태코드 변경은 회원탈퇴 기능 자체와는 직접적인 관련이 없어 범위 밖의 변경으로 보입니다. FollowService와 UserController의 변경사항을 별도의 PR로 분리하거나, 이들이 회원탈퇴 기능에 필수적인 변경임을 명확히 설명하는 PR 설명을 추가해주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목 '[FEAT] 회원탈퇴 API 개발'은 변경사항의 핵심을 정확히 요약하고 있으며, 회원탈퇴 API 개발이라는 주요 기능을 명확하게 전달합니다.
Linked Issues check ✅ Passed PR의 모든 코딩 요구사항이 연결된 이슈 #59를 충족합니다: SOFT DELETE를 사용한 회원탈퇴 API가 구현되었고, AuthController의 DELETE /withdraw 엔드포인트와 User 도메인의 updatedeleted 메서드가 추가되었습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/withdraw

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

@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: 3

🧹 Nitpick comments (2)
src/main/java/team/wego/wegobackend/user/domain/User.java (1)

141-143: updatedeleted 메서드 네이밍/시그니처 개선 제안

기능 자체는 단순히 soft delete 플래그를 토글하는 것으로 문제 없지만,

  • 메서드명은 updatedeleted보다 updateDeleted(또는 markDeleted, changeDeleted)처럼 camelCase를 맞추는 편이 가독성에 좋습니다.
  • 컬럼이 nullable = false이므로, 파라미터 타입을 Boolean 대신 boolean으로 두면 null 전달에 의한 런타임 오류 가능성을 줄일 수 있습니다.

다른 updateXxx 계열 메서드와 함께 정리해 두면 도메인 모델을 이해하기 더 쉬울 것 같습니다.

src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java (1)

128-136: Refresh 토큰 쿠키 보안 속성은 적절하나, CSRF 대응 전체 전략 점검 권장

createRefreshTokenCookie / deleteRefreshTokenCookie에서 HttpOnly, Secure, SameSite=Strict, Path=/를 모두 설정한 점은 좋습니다. 다만 애플리케이션이 쿠키 기반 인증을 일부라도 사용하고 있다면(특히 /refresh), 전체적인 CSRF 방어 전략(Spring Security CSRF 설정, CORS, 프론트엔드 호출 패턴 등)을 한 번 더 점검해 두는 것이 안전합니다.

예를 들어:

  • 세션/폼 기반 인증을 사용한다면 Spring Security CSRF 토큰 사용 여부,
  • 순수 JWT 헤더 기반이라면, 쿠키는 오직 refresh 용도로만 쓰이고 민감한 상태 변경 API에서는 헤더 기반 인증만 사용하는지

정도를 확인해 두면 좋겠습니다.

Also applies to: 141-148

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91a2a98 and f99a5fb.

📒 Files selected for processing (6)
  • src/main/java/team/wego/wegobackend/auth/application/AuthService.java (3 hunks)
  • src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java (5 hunks)
  • src/main/java/team/wego/wegobackend/auth/presentation/AuthControllerDocs.java (3 hunks)
  • src/main/java/team/wego/wegobackend/user/application/FollowService.java (2 hunks)
  • src/main/java/team/wego/wegobackend/user/domain/User.java (1 hunks)
  • src/main/java/team/wego/wegobackend/user/presentation/UserController.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-07T11:11:53.287Z
Learnt from: Be-HinD
Repo: WeGo-Together/WeGo_BackEnd PR: 32
File: src/test/http/auth/auth-api.http:25-27
Timestamp: 2025-12-07T11:11:53.287Z
Learning: IntelliJ HTTP client (.http files) automatically manages cookies between requests in the same file. When reviewing .http test files, a refresh token endpoint test does not need an explicit Cookie header because cookies from previous requests (e.g., login) are automatically included by the IDE.

Applied to files:

  • src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java
🧬 Code graph analysis (1)
src/main/java/team/wego/wegobackend/auth/application/AuthService.java (2)
src/main/java/team/wego/wegobackend/user/exception/UserNotFoundException.java (1)
  • UserNotFoundException (6-11)
src/main/java/team/wego/wegobackend/auth/exception/UserNotFoundException.java (1)
  • UserNotFoundException (6-11)
🪛 ast-grep (0.40.0)
src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java

[warning] 147-147: The application does not appear to verify inbound requests which can lead to a Cross-site request forgery (CSRF) vulnerability. If the application uses cookie-based authentication, an attacker can trick users into sending authenticated HTTP requests without their knowledge from any arbitrary domain they visit. To prevent this vulnerability start by identifying if the framework or library leveraged has built-in features or offers plugins for CSRF protection. CSRF tokens should be unique and securely random. The Synchronizer Token or Double Submit Cookie patterns with defense-in-depth mechanisms such as the sameSite cookie flag can help prevent CSRF. For more information, see: [Cross-site request forgery prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Req\ uest_Forgery_Prevention_Cheat_Sheet.html).
Context: response.addCookie(deleteCookie);
Note: [CWE-352] Cross-Site Request Forgery (CSRF). [REFERENCES]
- https://stackoverflow.com/questions/42717210/samesite-cookie-in-java-application

(cookie-missing-samesite-java)

🔇 Additional comments (3)
src/main/java/team/wego/wegobackend/user/application/FollowService.java (1)

47-48: 팔로우/언팔로우 시 카운트 갱신 로직 적절

팔로우 생성/삭제 이후에 팔로워·팔로이 카운트를 도메인 메서드로 증감시키는 구조가 자연스럽고, 트랜잭션 안에서 영속 엔티티를 수정하는 방식도 문제 없어 보입니다.

Also applies to: 68-69

src/main/java/team/wego/wegobackend/user/presentation/UserController.java (1)

124-125: 언팔로우 응답 코드 200으로 변경 타당

DELETE 요청에 201(Created) 대신 200(OK)을 반환하도록 수정한 부분이 HTTP语義에 더 잘 맞습니다. ApiResponse 내부 코드도 200으로 맞춰 일관성 있습니다.

src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java (1)

75-86: Refresh 토큰 쿠키 삭제 로직 공통화는 좋습니다

logout에서 직접 쿠키 속성을 세팅하던 코드를 deleteRefreshTokenCookie로 추출하고, SameSite=Strict, HttpOnly, Secure, Path=/, MaxAge=0를 모두 일관되게 설정한 점이 좋습니다. 중복 코드 제거와 함께 쿠키 속성 누락 위험도 줄어들었습니다.

Also applies to: 137-149

import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

문서의 회원탈퇴 설명(DB Soft Delete)와 실제 구현 불일치

Docs 인터페이스 시그니처는 AuthController 구현과 잘 맞지만, 설명에는 *"DB Soft Delete + refreshCookie 제거"*라고 되어 있는 반면 현재 AuthController.withDraw는 refresh 쿠키 삭제만 수행하고, AuthService.withDraw를 호출하지 않습니다.

문서와 실제 동작을 일치시키기 위해서는:

  • AuthController.withDraw에서 authService.withDraw(userDetails.getId())를 호출해 soft delete를 수행하거나,
  • (만약 의도적으로 아직 미구현이라면) 설명을 수정해 현재 동작을 정확하게 표현해야 합니다.

현재 상태는 API 계약과 구현이 어긋난 상태이므로 정리가 필요해 보입니다.

Also applies to: 17-17, 38-42

🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/auth/presentation/AuthControllerDocs.java
around lines 8, 17 and 38-42, the Javadoc/description claims "DB Soft Delete +
refreshCookie removal" but the actual AuthController.withDraw implementation
only removes the refresh cookie and does not call AuthService.withDraw; either
update the controller to call authService.withDraw(userDetails.getId()) before
removing the cookie so the soft-delete is performed, or update the docs text to
accurately reflect that only the refresh cookie is removed (no DB soft delete);
pick one approach, implement the corresponding change, and keep the method
signature/comments consistent with the chosen behavior.

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: 0

🧹 Nitpick comments (2)
src/main/java/team/wego/wegobackend/auth/application/AuthService.java (1)

111-123: 회원탈퇴 서비스 트랜잭션 및 soft delete 구현이 요구사항에 부합합니다

클래스가 @Transactional(readOnly = true)인데, withDraw에 별도 @Transactional을 붙여서 쓰기 트랜잭션을 보장한 점이 좋습니다. user.updatedeleted(true)로 soft delete 플래그만 변경하는 구조도 회원탈퇴 요구사항에 맞습니다.

추가로, 메서드명은 일반적으로 withdraw로 쓰는 편이 많으니, 추후 리팩터링 시 컨트롤러/Docs와 함께 이름을 정리해 두면 가독성이 더 좋아질 것 같습니다.

src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java (1)

88-103: 회원탈퇴 엔드포인트가 서비스 로직과 잘 연결되었습니다

@DeleteMapping("/withdraw")에서 @AuthenticationPrincipal CustomUserDetails로 본인 식별 후 authService.withDraw(userDetails.getId())를 호출하고, 이어서 refresh 토큰 쿠키까지 제거하는 흐름이 요구사항(soft delete + 토큰 정리)에 맞게 잘 구성되어 있습니다.

선택적으로는:

  • 메서드명/엔드포인트명을 withdraw로 통일(서비스/Docs 포함)하거나,
  • DELETE 응답을 204 No Content + body 없음 패턴으로 맞추는 등

API 일관성을 위한 소규모 리팩터링을 고려해 볼 수 있겠습니다만, 현재 구현도 기능적으로는 문제 없어 보입니다.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f99a5fb and 696c2e5.

📒 Files selected for processing (3)
  • src/main/java/team/wego/wegobackend/auth/application/AuthService.java (3 hunks)
  • src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java (5 hunks)
  • src/main/java/team/wego/wegobackend/common/security/SecurityEndpoints.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-07T11:11:53.287Z
Learnt from: Be-HinD
Repo: WeGo-Together/WeGo_BackEnd PR: 32
File: src/test/http/auth/auth-api.http:25-27
Timestamp: 2025-12-07T11:11:53.287Z
Learning: IntelliJ HTTP client (.http files) automatically manages cookies between requests in the same file. When reviewing .http test files, a refresh token endpoint test does not need an explicit Cookie header because cookies from previous requests (e.g., login) are automatically included by the IDE.

Applied to files:

  • src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java
🧬 Code graph analysis (1)
src/main/java/team/wego/wegobackend/auth/application/AuthService.java (2)
src/main/java/team/wego/wegobackend/user/exception/UserNotFoundException.java (1)
  • UserNotFoundException (6-11)
src/main/java/team/wego/wegobackend/auth/exception/UserNotFoundException.java (1)
  • UserNotFoundException (6-11)
🪛 ast-grep (0.40.0)
src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java

[warning] 148-148: The application does not appear to verify inbound requests which can lead to a Cross-site request forgery (CSRF) vulnerability. If the application uses cookie-based authentication, an attacker can trick users into sending authenticated HTTP requests without their knowledge from any arbitrary domain they visit. To prevent this vulnerability start by identifying if the framework or library leveraged has built-in features or offers plugins for CSRF protection. CSRF tokens should be unique and securely random. The Synchronizer Token or Double Submit Cookie patterns with defense-in-depth mechanisms such as the sameSite cookie flag can help prevent CSRF. For more information, see: [Cross-site request forgery prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Req\ uest_Forgery_Prevention_Cheat_Sheet.html).
Context: response.addCookie(deleteCookie);
Note: [CWE-352] Cross-Site Request Forgery (CSRF). [REFERENCES]
- https://stackoverflow.com/questions/42717210/samesite-cookie-in-java-application

(cookie-missing-samesite-java)

🔇 Additional comments (2)
src/main/java/team/wego/wegobackend/common/security/SecurityEndpoints.java (1)

5-18: PUBLIC_PATTERNS 세분화로 인증 경계가 명확해졌습니다

기존 "/api/v*/auth/**" 와일드카드를 제거하고, signup/login/refresh만 공개로 두어 withdraw(및 logout)가 반드시 인증된 사용자만 접근하도록 한 설계가 적절해 보입니다. 회원탈퇴 API 보안 요구사항과도 잘 맞습니다.

src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java (1)

75-86: Refresh 토큰 쿠키 삭제 로직 공통화가 깔끔합니다

logout에서 직접 쿠키를 조작하던 부분을 deleteRefreshTokenCookie 헬퍼로 분리해, 회원탈퇴와 로그아웃이 동일한 속성(이름, path, HttpOnly, Secure, SameSite=Strict)으로 쿠키를 제거하도록 만든 점이 좋습니다. 중복 제거 + 보안 속성 일관성 모두 확보되어 유지보수성이 높아졌습니다.

Also applies to: 138-150

@Be-HinD Be-HinD merged commit 6c728b9 into main Dec 11, 2025
1 check passed
@Be-HinD Be-HinD deleted the feat/withdraw branch December 11, 2025 16:48
@github-project-automation github-project-automation bot moved this from Backlog to Done in WeGo-Together Backend Dec 11, 2025
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

Status: Done

Development

Successfully merging this pull request may close these issues.

[FEAT] 회원탈퇴 API 개발

1 participant

Comments