Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat : 회원탈퇴 API 구현 #18

Merged
merged 9 commits into from
Jul 8, 2024
Merged

Feat : 회원탈퇴 API 구현 #18

merged 9 commits into from
Jul 8, 2024

Conversation

jsilver01
Copy link
Member

@jsilver01 jsilver01 commented Jul 7, 2024

요약 (Summary)

  • 회원탈퇴 API 구현하였습니다.
  • 회원이 탈퇴하면 해당 회원과 관련된 모든 데이터들이 DELETE 처리됩니다.
  • 레디스에서 해당 회원의 깃허브 아이디(키값) 으로 리프레시 토큰값을 찾아, 레디스에서 삭제함으로 토큰에 대한 유효성을 만료시켰습니다.
  • request, response dto 는 필요하지 않아서 생성하지 않았습니다. 회원탈퇴 api 명세서

🔑 변경 사항 (Key Changes)

  • JwtAuthenticationFilter 수정 : 해당 코드에 api 요청이 들어왔을 때, 토큰이 레디스에 있는지 확인하는 부분이 누락되어 있어, 추가하였습니다. 구현된 코드에서 토큰을 발급할 때에 subject 로 githubId 를 사용하고 claim 으로 memberId 를 사용합니다. 따라서 두가지 값을 모두 추출할 수 있고, 저는 레디스에 String 값인 githubId 를 키값으로 리프레시토큰을 value 로 저장하기 때문에 githubId 를 추출하여 레디스에서 찾는 쪽으로 구현하였습니다. 만약에 레디스에서 사용자를 찾을 수 없다면 403 forbidden 으로 막히게 됩니다.
  • TokenService 수정 : 이전 코드에서는 token 으로 레디스에서 삭제하는 코드들이었는데, 위에서 말했듯이 레디스에 키 : gitbhuId, 값 : refreshToken 이렇게 저장하기 때문에 키값으로 찾으려면 파라미터 값이 token -> githubId 로 변경되어야했습니다. 따라서 파라미터로 받는 값을 수정하였습니다. 즉, 깃허브 아이디로 레디스를 찾는다고 보면 됩니다.
  • JwtProvider 메소드 추가 : JwtProvider 에 엑세스토큰에서 githubId 를 추출하는 메소드 추가하였습니다.
  • MemberController.deleteMember 작성 : 컨트롤러에 회원 탈퇴를 처리하는 컨트롤러 작성하였습니다.
  • Member, Studyroom, MemberStudyroom 도메인 수정 : 도메인 코드에 updateStatus 메소드 추가하였습니다. status 를 DELETE 로 변경하기 위해 추가하였습니다.
  • BaseTime 수정 : 구현 중 modified_at 필드가 업데이트 되지 않는 오류 발견해서 확인하던 중에 어노테이션이 @ModifiedBy 로 잘못들어가 있는 것을 확인해서 @ModifiedDate 로 수정하였습니다.
  • MemberService.deleteMember 작성 : 회원탈퇴를 위한 서비스 코드입니다. memberStudyroomService 에 member_studyroom 에 관련된 데이터들의 delete 처리를 넘겼습니다. member 테이블에서 해당 사용자의 status 를 DELETE 로 업데이트하였고, tokenService.invalidateToken 를 사용하여 레디스에서 지우는 작업도 수행하였습니다. 아직 자료실이 구현되지 않아 탈퇴하는 회원의 자료 처리가 안되어있습니다. 추후에 추가로 수정하도록 하겠습니다.
  • MemberStudyroomService.deleteMember 작성: 회원탈퇴를 하는 회원의 역할(CAPTAIN/CREW) 에 따라 다르게 처리하도록 구현하였습니다. 만약 CAPTAIN 이라면 해당 스터디룸 또한 DELETE 처리하고, 스터디룸에 속한 다른 사용자의 데이터도 DELETE 처리하였습니다. (스터디룸이 사라져버렸으니, 빈 스터디룸에는 사용자가 ACTIVE 한 상태일 수 없습니다.) 만약 CREW 라면 단순히 사용자만 DELETE 처리하였습니다.
  • exception 추가 : 적절한 예외처리를 위해 exception 추가하였습니다.

📝 리뷰 요구사항 (To Reviewers)

  • 멤버를 Member 테이블에서 DELETE 처리 하는지
  • 멤버가 만약 CAPTAIN 이라면 해당 스터디룸을 DELETE 처리하고, Member_Studyroom 테이블에서 삭제 처리된 스터디룸의 id 를 가진 데이터들 또한 DELETE 처리 되는지
  • 멤버가 만약 CREW 라면, 스터디룸과 다른 데이터들은 건들지 않고 오직 자기 자신만 Member_Studyroom 테이블에서 삭제 처리하는지
  • 로그인하면, 레디스에 깃허브 아이디로 잘 들어가는지 (keys * 로 확인가능 -> 혹시 키값으로 확인하는 방법은 까먹으셨다면 이전 pr 에서 맥에 레디스 까는 법에 대한 링크를 참고해주세요!)
  • 회원 탈퇴 api 를 실행시키고 다시 레디스를 확인해봤을 때 데이터가 잘 지워졌는지
  • 데이터가 지워진 것을 확인하고, 지워진 사용자의 엑세스토큰을 헤더에 포함시켜 다른 api 를 호출하였을 때 403 이 반환되는지

확인 방법

❗️application-local.yml 파일의 데이터베이스 설정을 로컬에 맞췄는지 확인해주세요.

먼저 코드를 실행시키고 레디스도 실행시켜주세요.
redis-cli 를 입력하고 keys *를 입력했을 때 (empty array) 라면 바로 아래의 쿼리문을 실행시키고, 만약 데이터가 존재한다면 FLUSHDB 을 입력하여 초기화해 주세요.

use linkode;

INSERT INTO avatar (created_at, modified_at, avatar_img, status) VALUES
('2024-06-30 12:00:00.000000', '2024-06-30 12:30:00.000000', 'img1.png', 'ACTIVE');

INSERT INTO member (created_at, modified_at, avatar_id, github_id, nickname, color,status) VALUES
('2024-06-30 12:00:00.000000', '2024-06-30 12:30:00.000000', 1, 'Mouon', '두바이초콜릿','#FFFFF', 'ACTIVE');
INSERT INTO member (created_at, modified_at, avatar_id, github_id, nickname, color,status) VALUES
('2024-06-30 12:00:00.000000', '2024-06-30 12:30:00.000000', 1, 'jsilver01', '애플코드','#FFFFF', 'ACTIVE');

INSERT INTO studyroom (created_at, modified_at, studyroom_name, studyroom_profile, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 'New Studyroom', 'Profile for New Studyroom', 'ACTIVE');
INSERT INTO studyroom (created_at, modified_at, studyroom_name, studyroom_profile, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 'New Studyroom 2', 'Profile for New Studyroom', 'ACTIVE');
INSERT INTO studyroom (created_at, modified_at, studyroom_name, studyroom_profile, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 'New Studyroom 3', 'Profile for New Studyroom', 'ACTIVE');
INSERT INTO studyroom (created_at, modified_at, studyroom_name, studyroom_profile, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 'New Studyroom 4', 'Profile for New Studyroom', 'ACTIVE');

INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 1, 1, 'CAPTAIN', 'ACTIVE');
INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 1, 2, 'CREW', 'ACTIVE');
INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 1, 3, 'CAPTAIN', 'ACTIVE');
INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 1, 4, 'CREW', 'ACTIVE');
INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 2, 1, 'CREW', 'ACTIVE');
INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 2, 2, 'CAPTAIN', 'ACTIVE');
INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 2, 3, 'CREW', 'ACTIVE');
INSERT INTO member_studyroom (created_at, modified_at, member_id, studyroom_id, role, status) VALUES
('2024-07-04 12:00:00.000000', '2024-07-04 12:00:00.000000', 2, 4, 'CAPTAIN', 'ACTIVE');

이 쿼리문을 실행시켜주세요.
그 다음 로그인을 진행해주세요.
레디스에서 다시 keys * 를 입력하고 깃허브 id 로 키값이 들어간 것을 확인해주세요.
그 다음 PATCH 메소드로 아래의 요청을 보내주세요. 헤더에는 로그인에서 받은 "엑세스" 토큰을 넣어서 보내주세요.

http://localhost:8080/user
스크린샷 2024-07-08 오전 12 30 58

로그인 후 레디스에 저장된 모습입니다.

스크린샷 2024-07-08 오전 12 26 23

요청에 성공하면 데이터베이스로 들어가서 값들이 잘 처리되었는지 확인해주세요.

스크린샷 2024-07-08 오전 12 27 05 스크린샷 2024-07-08 오전 12 27 27 스크린샷 2024-07-08 오전 12 27 51 스크린샷 2024-07-08 오전 12 29 07 스크린샷 2024-07-08 오전 12 29 49

저는 회원탈퇴한 사용자의 토큰을 스터디룸 수정 api 에 넣어보았는데 403 이 뜬 것을 확인할 수 있습니다.
리뷰하실 때에는 delete 처리되는 값이 전부 저랑 반대여야 성공입니다.

@jsilver01 jsilver01 requested a review from Mouon July 7, 2024 15:33
@Mouon
Copy link
Member

Mouon commented Jul 7, 2024

모든 리뷰항목확인하였습니다! 구현하신 목적에맞게 잘 작동하는것 확인했습니다!
생각하지못했던 비즈니스 로직까지 꼼꼼하게 신경쓰셔서 좋은것 같습니다!
수고하셨습니다!

포스트맨

스크린샷 2024-07-08 오전 10 02 47

레디스에서 삭제된 모습

스크린샷 2024-07-08 오전 10 03 04

데이터 베이스상 처리된 모습

맴버 테이블

스크린샷 2024-07-08 오전 10 03 32

맴버 스터디룸 테이블

스크린샷 2024-07-08 오전 10 04 18

스터디룸 테이블

스크린샷 2024-07-08 오전 10 04 45

@Mouon
Copy link
Member

Mouon commented Jul 8, 2024

기존에는 키값이 저장됬는데
변경후에는 아이디 그대로 저장되는데 변경된 이유가 궁금합니다! (순수 질문)

@jsilver01
Copy link
Member Author

기존에는 키값이 저장됬는데 변경후에는 아이디 그대로 저장되는데 변경된 이유가 궁금합니다! (순수 질문)

앜ㅋㅋ 저희가 엑세스토큰이랑 리프레시 토큰 2개를 발급하잖아요 리프레시 토큰이 훨씬 유효기간이 기니까 만료된 엑세스토큰의 재발급을 위해 리프레시토큰을 키값으로 저장했는데(근데..아직 재발급 하는 부분은 구현되지 않았..습니다.. 이것두 추후에 다시 해볼게요 당장 급한건아니라..) 헤더로 들어오는건 엑세스토큰이란 말이죠 그러면 그 토큰으로 레디스를 찾아봐야 일치하는게 당연히 없으니까 엑세스토큰받음->깃허브아이디뽑음->레디스의 리프레시 토큰에서 for 문같은거 돌면서 일일히 깃허브 아이디 추출함->엑세스토큰의 아이디랑 일치하는지 확인 이 과정을 거쳐야하는거같더라구요. 근데 깃허브 아이디를 키값으로 저장해두면 엑세스토큰에서 추출한 깃허브 아이디로 바로 찾으면 되니까 비교하는 과정이 줄어드는 것 같아서 수정하게되었습니다!

@Mouon
Copy link
Member

Mouon commented Jul 8, 2024

오! 답변감사합니다!

@Mouon Mouon merged commit 4757c16 into develop Jul 8, 2024
@Mouon Mouon deleted the LINKODE-5-BE-회원탈퇴 branch July 9, 2024 08:37
@Mouon Mouon added the Feature Make Feat label Sep 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Make Feat
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants