From c2d93733e869945963af19f420a3b43134e0ff35 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 00:44:01 +0900 Subject: [PATCH 01/12] =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20&?= =?UTF-8?q?=20dto=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 11 ++++++++++- .../dto/request/MemberWithdrawalRequest.java | 17 +++++++++++++++++ .../domain/member/service/MemberService.java | 6 ++++++ .../global/exeption/dto/ExceptionCode.java | 1 + 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java index ce1a57e..13cd676 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import kr.ac.ks.cs_web_back.domain.member.controller.code.MemberSuccessCode; import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberCreateRequest; +import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberWithdrawalRequest; import kr.ac.ks.cs_web_back.domain.member.service.MemberService; import kr.ac.ks.cs_web_back.global.response.CsResponse; import lombok.RequiredArgsConstructor; @@ -24,4 +25,12 @@ public CsResponse register( Long id = memberService.createMember(request); return CsResponse.of(MemberSuccessCode.GENERATED_REGISTERED, id); } -} + @PostMapping("/withdrawal") + @ResponseStatus(HttpStatus.OK) + public CsResponse withdraw( + @Valid @RequestBody MemberWithdrawalRequest request + ) { + Long id = memberService.withdraw(request); + return CsResponse.of(MemberSuccessCode.OK_WITHDRAWN, id); + } +} \ No newline at end of file diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java new file mode 100644 index 0000000..67fa29a --- /dev/null +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java @@ -0,0 +1,17 @@ +package kr.ac.ks.cs_web_back.domain.member.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.*; + +@Schema(description = "회원탈퇴 요청 DTO") +public record MemberWithdrawalRequest( + + @Schema(description = "사용자명", example = "userNickName") + @NotNull(message = "사용자명이 입력되지 않았습니다.") + String Username, + + @Schema(description = "비밀번호", example = "examplePassword123") + @NotBlank(message = "비밀번호가 입력되지 않았습니다.") + String password +){ +} diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java index bacb9a8..8b2e057 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java @@ -2,6 +2,7 @@ import kr.ac.ks.cs_web_back.domain.member.controller.code.MemberExceptionCode; import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberCreateRequest; +import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberWithdrawalRequest; import kr.ac.ks.cs_web_back.domain.member.model.Member; import kr.ac.ks.cs_web_back.domain.member.repository.MemberRepository; import kr.ac.ks.cs_web_back.global.exeption.domain.ConflictException; @@ -39,6 +40,11 @@ public Long createMember(MemberCreateRequest request) { return memberRepository.save(member).getId(); } + public Long withdraw(MemberWithdrawalRequest request) { + Member member = memberRepository.findById(request.username()) + .orElseThrow(() -> new ) + } + @Override @Transactional(readOnly = true) public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { diff --git a/src/main/java/kr/ac/ks/cs_web_back/global/exeption/dto/ExceptionCode.java b/src/main/java/kr/ac/ks/cs_web_back/global/exeption/dto/ExceptionCode.java index d714162..a1a3adb 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/global/exeption/dto/ExceptionCode.java +++ b/src/main/java/kr/ac/ks/cs_web_back/global/exeption/dto/ExceptionCode.java @@ -4,3 +4,4 @@ public interface ExceptionCode { int getCode(); String getMessage(); } + From 2b93a7dad224cdf88d861fddcacc4ca5dd2875b7 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 00:44:45 +0900 Subject: [PATCH 02/12] =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20&?= =?UTF-8?q?=20dto=20&=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20feat/#9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/code/MemberExceptionCode.java | 1 + .../dto/request/MemberWithdrawalRequest.java | 4 +++- .../cs_web_back/domain/member/model/Member.java | 17 +++++++++++++++++ .../domain/member/service/MemberService.java | 13 ++++++++++++- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java index 2dd961a..06ee8e1 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java @@ -14,6 +14,7 @@ public enum MemberExceptionCode implements ExceptionCode { CONFLICT_EMAIL(5010, "이미 존재하는 이메일입니다."), CONFLICT_USERNAME(5012, "이미 존재하는 사용자명입니다."), NOT_FOUND_USER(6001, "일치하는 사용자가 존재하지 않습니다."), + UNAUTHORIZED_PASSWORD(8011, "비밀번호가 일치하지 않습니다."), ; private final int code; diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java index 67fa29a..5d01c32 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java @@ -14,4 +14,6 @@ public record MemberWithdrawalRequest( @NotBlank(message = "비밀번호가 입력되지 않았습니다.") String password ){ -} + public Long username() { + } +} \ No newline at end of file diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java index ac4c508..3bcdc40 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java @@ -10,8 +10,12 @@ import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDate; +<<<<<<< HEAD import java.util.Collection; import java.util.Collections; +======= +import java.time.LocalDateTime; +>>>>>>> 65597fa (컨트롤러 & dto & 서비스 구현 feat/#9) @Entity @Getter @@ -36,6 +40,13 @@ public class Member extends BaseEntity implements UserDetails { @Column private String number; + @Column(name = "is_withdrawn", nullable = false) + private boolean isWithdrawn; + + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + + @Builder private Member(String email, String password, String username, LocalDate birthdate, String number) { this.email = email; @@ -45,6 +56,7 @@ private Member(String email, String password, String username, LocalDate birthd this.number = number; } +<<<<<<< HEAD public String getNickname() { return username; } @@ -57,5 +69,10 @@ public Collection getAuthorities() { @Override public String getUsername() { return email; +======= + public void withdrawNow(){ + this.isWithdrawn = true; + this.deletedAt = LocalDateTime.now(); +>>>>>>> 65597fa (컨트롤러 & dto & 서비스 구현 feat/#9) } } diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java index 8b2e057..5bf17a9 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java @@ -6,6 +6,8 @@ import kr.ac.ks.cs_web_back.domain.member.model.Member; import kr.ac.ks.cs_web_back.domain.member.repository.MemberRepository; import kr.ac.ks.cs_web_back.global.exeption.domain.ConflictException; +import kr.ac.ks.cs_web_back.global.exeption.domain.NotFoundException; +import kr.ac.ks.cs_web_back.global.exeption.domain.UnauthorizedException; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -42,7 +44,16 @@ public Long createMember(MemberCreateRequest request) { public Long withdraw(MemberWithdrawalRequest request) { Member member = memberRepository.findById(request.username()) - .orElseThrow(() -> new ) + .orElseThrow(() -> new NotFoundException(MemberExceptionCode.NOT_FOUND_USER)); + + if (!passwordEncoder.matches(request.password(),member.getPassword())) { + throw new UnauthorizedException(MemberExceptionCode.UNAUTHORIZED_PASSWORD); + } + + member.withdrawNow(); + memberRepository.save(member); + + return member.getId(); } @Override From e08371ed098bcac5c53d725963a3f27aa7c2d0f2 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 00:46:39 +0900 Subject: [PATCH 03/12] =?UTF-8?q?fix(#9):=20=EB=A6=AC=EB=B2=A0=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=8B=A4=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/ac/ks/cs_web_back/domain/member/model/Member.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java index 3bcdc40..4a1e00f 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java @@ -10,12 +10,9 @@ import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDate; -<<<<<<< HEAD import java.util.Collection; import java.util.Collections; -======= import java.time.LocalDateTime; ->>>>>>> 65597fa (컨트롤러 & dto & 서비스 구현 feat/#9) @Entity @Getter @@ -56,7 +53,6 @@ private Member(String email, String password, String username, LocalDate birthd this.number = number; } -<<<<<<< HEAD public String getNickname() { return username; } @@ -69,10 +65,10 @@ public Collection getAuthorities() { @Override public String getUsername() { return email; -======= + } + public void withdrawNow(){ this.isWithdrawn = true; this.deletedAt = LocalDateTime.now(); ->>>>>>> 65597fa (컨트롤러 & dto & 서비스 구현 feat/#9) } } From b1203befbf4a54b687ca37d603babba78ceeda63 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 00:59:59 +0900 Subject: [PATCH 04/12] =?UTF-8?q?feat(#9):=20=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20dto=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/MemberWithdrawalRequest.java | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java deleted file mode 100644 index 5d01c32..0000000 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/dto/request/MemberWithdrawalRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package kr.ac.ks.cs_web_back.domain.member.dto.request; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.*; - -@Schema(description = "회원탈퇴 요청 DTO") -public record MemberWithdrawalRequest( - - @Schema(description = "사용자명", example = "userNickName") - @NotNull(message = "사용자명이 입력되지 않았습니다.") - String Username, - - @Schema(description = "비밀번호", example = "examplePassword123") - @NotBlank(message = "비밀번호가 입력되지 않았습니다.") - String password -){ - public Long username() { - } -} \ No newline at end of file From 52ff2da31376f6cb53247f64795870c9c9a81748 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:00:33 +0900 Subject: [PATCH 05/12] =?UTF-8?q?refactor(#9):=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/controller/code/MemberExceptionCode.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java index 06ee8e1..6fed1fa 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/code/MemberExceptionCode.java @@ -9,11 +9,10 @@ public enum MemberExceptionCode implements ExceptionCode { BAD_REQUEST_NO_EMAIL(9010, "이메일이 입력되지 않았습니다."), - BAD_REQUEST_NO_PASSWORD(9011, "비밀번호가 입력되지 않았습니다."), - BAD_REQUEST_NO_USERNAME(9012, "사용자명이 입력되지 않았습니다."), - CONFLICT_EMAIL(5010, "이미 존재하는 이메일입니다."), + BAD_REQUEST_NO_PASSWORD(9010, "비밀번호가 입력되지 않았습니다."), + BAD_REQUEST_NO_USERNAME(9010, "사용자명이 입력되지 않았습니다."), + CONFLICT_EMAIL(5010, "이미 가입된 이메일입니다."), CONFLICT_USERNAME(5012, "이미 존재하는 사용자명입니다."), - NOT_FOUND_USER(6001, "일치하는 사용자가 존재하지 않습니다."), UNAUTHORIZED_PASSWORD(8011, "비밀번호가 일치하지 않습니다."), ; From 4f32b40e4417da4a142a0f6ef6e311943a845c2d Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:01:02 +0900 Subject: [PATCH 06/12] =?UTF-8?q?feat(#9):=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/controller/MemberController.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java index 13cd676..d50d05b 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java @@ -3,8 +3,9 @@ import jakarta.validation.Valid; import kr.ac.ks.cs_web_back.domain.member.controller.code.MemberSuccessCode; import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberCreateRequest; -import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberWithdrawalRequest; +import kr.ac.ks.cs_web_back.domain.member.model.Member; import kr.ac.ks.cs_web_back.domain.member.service.MemberService; +import kr.ac.ks.cs_web_back.global.annotation.IdentifiedUser; import kr.ac.ks.cs_web_back.global.response.CsResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -28,9 +29,9 @@ public CsResponse register( @PostMapping("/withdrawal") @ResponseStatus(HttpStatus.OK) public CsResponse withdraw( - @Valid @RequestBody MemberWithdrawalRequest request + @IdentifiedUser Member member ) { - Long id = memberService.withdraw(request); - return CsResponse.of(MemberSuccessCode.OK_WITHDRAWN, id); + memberService.deleteMember(member); + return CsResponse.of(MemberSuccessCode.OK_WITHDRAWN); } } \ No newline at end of file From c009f0e13a7a0f345d15489a563e93a46746689d Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:01:20 +0900 Subject: [PATCH 07/12] =?UTF-8?q?feat(#9):=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/service/MemberService.java | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java index 5bf17a9..5f81eb4 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/service/MemberService.java @@ -2,12 +2,9 @@ import kr.ac.ks.cs_web_back.domain.member.controller.code.MemberExceptionCode; import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberCreateRequest; -import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberWithdrawalRequest; import kr.ac.ks.cs_web_back.domain.member.model.Member; import kr.ac.ks.cs_web_back.domain.member.repository.MemberRepository; import kr.ac.ks.cs_web_back.global.exeption.domain.ConflictException; -import kr.ac.ks.cs_web_back.global.exeption.domain.NotFoundException; -import kr.ac.ks.cs_web_back.global.exeption.domain.UnauthorizedException; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -42,18 +39,8 @@ public Long createMember(MemberCreateRequest request) { return memberRepository.save(member).getId(); } - public Long withdraw(MemberWithdrawalRequest request) { - Member member = memberRepository.findById(request.username()) - .orElseThrow(() -> new NotFoundException(MemberExceptionCode.NOT_FOUND_USER)); - - if (!passwordEncoder.matches(request.password(),member.getPassword())) { - throw new UnauthorizedException(MemberExceptionCode.UNAUTHORIZED_PASSWORD); - } - - member.withdrawNow(); - memberRepository.save(member); - - return member.getId(); + public void deleteMember(Member member) { + memberRepository.delete(member); } @Override From a3a27113dc68bdeb5120a9f5b27ac3f6d129c3b7 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:01:31 +0900 Subject: [PATCH 08/12] =?UTF-8?q?feat(#9):=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EB=AA=A8=EB=8D=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ks/cs_web_back/domain/member/model/Member.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java index 4a1e00f..4fc5d4b 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java @@ -37,13 +37,6 @@ public class Member extends BaseEntity implements UserDetails { @Column private String number; - @Column(name = "is_withdrawn", nullable = false) - private boolean isWithdrawn; - - @Column(name = "deleted_at") - private LocalDateTime deletedAt; - - @Builder private Member(String email, String password, String username, LocalDate birthdate, String number) { this.email = email; @@ -66,9 +59,4 @@ public Collection getAuthorities() { public String getUsername() { return email; } - - public void withdrawNow(){ - this.isWithdrawn = true; - this.deletedAt = LocalDateTime.now(); - } } From 5590739ae0d1140843fac622671706f93a523b15 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:06:47 +0900 Subject: [PATCH 09/12] =?UTF-8?q?docs(#9):=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EB=AC=B8=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SpringDocMemberController.java | 13 +++++++++++++ .../ks/cs_web_back/domain/member/model/Member.java | 1 - 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/SpringDocMemberController.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/SpringDocMemberController.java index 1f5fd2e..66b405f 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/SpringDocMemberController.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/SpringDocMemberController.java @@ -1,9 +1,12 @@ package kr.ac.ks.cs_web_back.domain.member.controller; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberCreateRequest; +import kr.ac.ks.cs_web_back.domain.member.model.Member; +import kr.ac.ks.cs_web_back.global.annotation.IdentifiedUser; import kr.ac.ks.cs_web_back.global.response.CsResponse; import kr.ac.ks.cs_web_back.global.swagger.error.ApiErrorResponse; import kr.ac.ks.cs_web_back.global.swagger.error.ErrorCase; @@ -27,4 +30,14 @@ public interface SpringDocMemberController { CsResponse register( @RequestBody MemberCreateRequest request ); + + @Operation(summary = "회원탈퇴", description = "회원 탈퇴") + @ApiResponse(responseCode = "200", description = "회원 탈퇴에 성공했습니다.") + @ApiErrorResponse(status = HttpStatus.UNAUTHORIZED, instance = "/member/withdrawal", errorCases = { + @ErrorCase(description = "토큰 형식 이상", code = 8001, exampleMessage = "유효하지 않은 토큰입니다."), + @ErrorCase(description = "인증 실패 (토큰 만료 혹은 틀린 이메일 / 비밀번호)", code = 8002, exampleMessage = "인증에 실패했습니다.") + }) + CsResponse withdraw( + @Parameter(hidden = true) @IdentifiedUser Member member + ); } diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java index 4fc5d4b..ac4c508 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/model/Member.java @@ -12,7 +12,6 @@ import java.time.LocalDate; import java.util.Collection; import java.util.Collections; -import java.time.LocalDateTime; @Entity @Getter From 85daaf461c1dfd65e52e7de51f780f6fb0c647a3 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:09:09 +0900 Subject: [PATCH 10/12] =?UTF-8?q?fix(#9):=20=EB=B0=98=ED=99=98=EA=B0=92=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cs_web_back/domain/member/controller/MemberController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java index d50d05b..2743a43 100644 --- a/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java +++ b/src/main/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberController.java @@ -26,9 +26,10 @@ public CsResponse register( Long id = memberService.createMember(request); return CsResponse.of(MemberSuccessCode.GENERATED_REGISTERED, id); } + @PostMapping("/withdrawal") @ResponseStatus(HttpStatus.OK) - public CsResponse withdraw( + public CsResponse withdraw( @IdentifiedUser Member member ) { memberService.deleteMember(member); From ffd6ecf57dc793a4f777d258d663d70c70a33a4d Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:43:41 +0900 Subject: [PATCH 11/12] =?UTF-8?q?test(#9):=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MemberControllerTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberControllerTest.java b/src/test/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberControllerTest.java index 6e1ab09..0c59070 100644 --- a/src/test/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberControllerTest.java +++ b/src/test/java/kr/ac/ks/cs_web_back/domain/member/controller/MemberControllerTest.java @@ -2,9 +2,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberCreateRequest; +import kr.ac.ks.cs_web_back.domain.member.fixture.MemberFixture; +import kr.ac.ks.cs_web_back.domain.member.model.Member; import kr.ac.ks.cs_web_back.domain.member.service.MemberService; import kr.ac.ks.cs_web_back.global.jwt.JwtTokenResolver; import kr.ac.ks.cs_web_back.global.jwt.JwtUtil; +import kr.ac.ks.cs_web_back.global.resolver.IdentifiedUserArgumentResolver; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -13,6 +16,9 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.servlet.MockMvc; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -30,6 +36,9 @@ public class MemberControllerTest { @MockitoBean private JwtTokenResolver jwtTokenResolver; + @MockitoBean + private IdentifiedUserArgumentResolver identifiedUserArgumentResolver; + @Autowired private MockMvc mockMvc; @@ -155,5 +164,19 @@ public void tooLongUsernameReturns400BadRequest() throws Exception { .andExpect(status().isBadRequest()); } + @Test + @DisplayName("회원탈퇴 성공: 회원 탈퇴에 성공하면 200 Ok를 반환한다.") + public void withdrawalSuccessfullyReturns200Ok() throws Exception { + // given + String token = "Bearer valid-access-token"; + Member member = MemberFixture.memberFixture(); + given(identifiedUserArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(member); + doNothing().when(memberService).deleteMember(member); + + // when & then + mockMvc.perform(post("/member/withdrawal") + .header("Authorization", token)) + .andExpect(status().isOk()); + } } From 1f47300e8ad06bf03907477b1bbdd8a1c13ee693 Mon Sep 17 00:00:00 2001 From: wooki Date: Thu, 25 Sep 2025 01:43:57 +0900 Subject: [PATCH 12/12] =?UTF-8?q?test(#9):=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/service/MemberServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/kr/ac/ks/cs_web_back/domain/member/service/MemberServiceTest.java b/src/test/java/kr/ac/ks/cs_web_back/domain/member/service/MemberServiceTest.java index 926fdc0..097dbc2 100644 --- a/src/test/java/kr/ac/ks/cs_web_back/domain/member/service/MemberServiceTest.java +++ b/src/test/java/kr/ac/ks/cs_web_back/domain/member/service/MemberServiceTest.java @@ -2,6 +2,7 @@ import kr.ac.ks.cs_web_back.domain.member.controller.code.MemberExceptionCode; import kr.ac.ks.cs_web_back.domain.member.dto.request.MemberCreateRequest; +import kr.ac.ks.cs_web_back.domain.member.fixture.MemberFixture; import kr.ac.ks.cs_web_back.domain.member.model.Member; import kr.ac.ks.cs_web_back.domain.member.repository.MemberRepository; import kr.ac.ks.cs_web_back.global.exeption.domain.ConflictException; @@ -13,6 +14,8 @@ import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; +import java.util.Collection; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -103,6 +106,21 @@ void registeredFailedByConflictUsername() { }); } + @Test + @DisplayName("회원탈퇴 성공: 멤버 객체를 삭제한다.") + void shouldDeleteMember() { + // givent + Member member = MemberFixture.memberFixture(); + memberRepository.saveAndFlush(member); + + // when + memberService.deleteMember(member); + + // then + Collection members = memberRepository.findAll(); + assertThat(members).hasSize(0); + } + @Test @DisplayName("loadUserByUsername 실패: 존재하지 않는 이메일로 사용자 로드 시 UsernameNotFoundException이 발생한다.") void shouldThrowUsernameNotFoundExceptionWhenLoadingNonExistentUser() {