iamkanguk.dev

[맵필로그] 로그아웃 + 회원탈퇴 기능 구현 기록 본문

사이드 프로젝트/맵필로그

[맵필로그] 로그아웃 + 회원탈퇴 기능 구현 기록

iamkanguk 2024. 2. 14. 22:02

오늘은 맵필로그 프로젝트에서 로그아웃과 회원탈퇴 기능을 어떻게 구현했는지에 대해서 설명해보려고 한다.

먼저, 맵필로그에서는 카카오 로그인과 애플 로그인을 제공하고 있다는 것을 먼저 말씀드립니다!

 

크게 어렵지 않은 내용인 것 같아서 맛있는 거 드시면서 보셔도 충분합니당 ㅎㅎ

 

1.   로그아웃 기능

로그아웃 기능에서는 소셜쪽으로는 크게 기능구현을 할 게 없는 것 같다. 왜냐하면 애플 로그인은 회원탈퇴 시에만 Token을 Revoke 시켜주면 되기 때문에 따로 로그아웃 쪽에서는 할 게 없다. 그리고 카카오 로그인은 공식 문서를 보면 카카오에서 제공하는 Access-Token을 만료시키는 로직이 있는데 맵필로그 프로젝트에서는 카카오에서 주는 토큰을 따로 사용하지 않기 때문에 굳이 따로 처리하지는 않았다.

 

애플리케이션 단에서는 다음과 같이 처리했다.

  • 사용자 DB에서 FCM Token을 NULL 처리한다.
  • 필자의 경우 Access-Token + Refresh-Token을 사용하고 있는데, Redis에 저장되어 있는 Refresh-Token을 삭제해준다.
  • 그리고 Access-Token BlackList 기능을 사용하는데, Access-Token을 BlackList에 추가한다.

(1) FCM Token NULL 처리

이거는 사실 프로젝트의 성격상 다를 수 있는데 필자는 로그아웃을 하게 되면 알림을 유저에게 제공하지 않아야겠다고 생각해서 FCM Token을 NULL 처리 했다. 이거는 프로젝트 성격에 따라 처리하면 될 것 같다. 단순히 DB에서 NULL로 UPDATE만 해주면 되기 때문에 따로 코드 설명은 하지 않도록 하겠다.

(2) Redis에 저장되어 있는 Refresh-Token 삭제

로그아웃을 하게 되면 사용자 입장에서는 다시 로그인을 해야한다. 현재 맵필로그 쪽에서는 Refresh-Token을 통해 토큰을 재발급하는 로직이 있기 때문에 Redis에 저장되어 있는 Refresh-Token을 삭제해야 한다. 그러면 토큰을 재발급 받을 수 없고 새로 로그인을 해야한다.

그리고 아마 클라이언트 쪽에서는 저장하고 있던 Access-Token을 삭제할 것이다.

 

마찬가지로 Cache에서 단순히 삭제하는 것이기 때문에 코드 설명은 하지 않겠다.

(3) Access-Token BlackList

 

위의 코드는 필자가 Header에 담아서 보내주는 Access-Token을 받아서, 만료시간까지 포함해서 Controller에서 받아올 수 있도록 하는 Custom Decorator이다. BlackList를 적용한 이유는, 로그아웃을 하게 되면 Access-Token을 무효화 시켜주어야 하기 때문이다. 누군가 탈취하면 쓸 수 있기 때문!

 

당연히 이전에 사용자가 사용한 토큰은 무효화 시켜야 하는데 따로 Revoke 하는 기능은 제공되고 있지 않아서 Access Token을 BlackList에 저장시켜주고, 사용자 인증할 때 BlackList에 해당 키가 있는지 확인하고 없으면 인증을 통과한다. 이 때 Redis에 저장할 때 TTL은 Access-Token의 남은 만료시간(remainExpireTime)이다.

 

이렇게 기능을 구현하면 사용자에 대한 로그아웃은 어느정도 처리가 된 것 같다. 다음으로는 회원탈퇴 기능을 설명해보겠다!

 

2.  회원탈퇴 기능

 

위의 사진은 회원탈퇴 API의 Service 코드이다. 핵심인 부분만 조금 설명을 드려보도록 하겠다. 회원탈퇴 Flow는 다음과 같다.

  • 사용자 테이블에서 deletedAt 추가
  • 사용자 회원탈퇴 사유 테이블에 ROW 추가
  • Refresh-Token Redis에서 삭제 + Access-Token BlackList 추가
  • S3에서 사용자 프로필 이미지 삭제
  • (애플 로그인 유저의 경우) Revoke Token + (카카오 로그인 유저는 어떻게?)
  • 어제의 회원탈퇴 유저들을 파악하고 관련된 데이터를 삭제처리함 with CronJob

위의 기능들 중에서 설명이 조금 필요한 부분들을 설명드리도록 하겠다. 3번은 아까 로그아웃에서 설명했으니 생략!

 

(1) S3에서 사용자 프로필 이미지 삭제

 

사실 S3에서 굳이 삭제를 시켜줘야하나 싶긴 하다. 바로바로 삭제하지 않고 나중에 애플리케이션 쪽에서 사용하지 않는 이미지들을 한번에 다 가져와서 삭제처리 해줘도 될 것 같다. 일단 지금은 DB에 S3에 저장된 이미지의 key도 저장하는데 그걸 가져와서 이미지를 삭제처리 해준다. MulterBuilder 같은 경우에는 카카수님 블로그를 참고했으니 확인하면 좋을 것 같다!

 

(2) 애플 로그인 유저의 경우 Token Revoke + 카카오 로그인 유저는 어떻게?

 

먼저 시작전에 애플로그인 구현 기록에 대해서 보고 싶으시면 해당 포스팅을 확인하시면 좋을 것 같다! client_id와 같은 요소들은 따로 설명하지는 않겠다.

 

맵필로그에서는 애플 로그인할 때 애플에서 제공하는 refresh_token을 사용자 DB에 저장한다. 이 refresh_token을 가지고 애플 서버에 revoke 요청을 한다. 애플에서 제공하는 refresh_token은 유효시간이 없기 때문에 DB에 저장하고 사용할 수 있다.

 

그리고 카카오 로그인의 경우에는 Kakao Developers에 연결 끊기(unlink)가 있다. 이 부분은 좀 애매한 부분이 있다.

카카오 로그인에서 제공하는 access_token과 refresh_token은 모두 만료시간이 있다. access_token이 만료된 경우 refresh_token을 통해 갱신을 시켜주고 사용해야 한다.

 

그런데 맵필로그에서는 카카오에서 제공하는 토큰을 저장하지는 않는다. 물론 서버에서 저장해서 처리할 수 있지만, 이거는 클라이언트 분들에게 부탁을 드렸다. 클라이언트에서 로컬 저장소에 카카오 로그인을 할 때 token들을 저장하고, 앱단에서 전부 처리하기로 결정했다.

 

서버에서 처리하는게 맞긴 한 것 같은데 싶지만... 어쨌든 일단 위와 같이 구현했다!

 

(3) 어제의 회원탈퇴 유저 파악 후 관련 데이터 삭제 - CronJob

 

사실 CronJob으로 빼지 않고 사이드프로젝트 단계이기 때문에 회원탈퇴 API에서 전부 처리해도 괜찮긴 하다. 하지만 그냥 단순하게 경험으로 CronJob으로 빼서 처리를 해보고 싶다고 생각되어서 한번 해봤다.

 

매일 오전 5시에 Cron이 돌도록 설정을 했다. 그리고 어제 탈퇴한 사용자들 리스트를 가져온다.

그다음에 DB에 사용자가 생성한 Data들을 전부 불러와서 deletedAt을 추가해준다.

 

이렇게 필자처럼 Cron으로 빼서 하는 것도 하나의 경험이 될 수 있겠다 생각한다!


이렇게 로그아웃과 회원탈퇴 기능에 대해서 간단히 알아보았다. 크게 어려운 로직은 없던 것 같다. 다음에는 또 많이 고민한 로직에 대해서 설명하는 포스팅을 작성해보도록 하겠다!