Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

cchanmi

[iOS] 토큰 만료 플로우 이슈 해결 본문

iOS

[iOS] 토큰 만료 플로우 이슈 해결

cchanmi 2024. 6. 14. 22:40

최근 운영 중인 앱 서비스에서 스플래시에서 에러가 발생하여 앱이 멈추는 현상이 있었습니다. 해당 오류는 모든 유저한테서 공통적으로 발생하는 에러가 아니었기 때문에, 어떠한 문제로인해 발생하는 에러인지 원인을 알기가 어려웠습니다.

 

 

유저가 스플래시 뷰에서 다음 화면으로 넘어가지 못하고 앱이 멈추는 현상은 크리티컬한 현상이었기 때문에, 원인을 찾고자 팀원들과 열심히 디버깅했었던 기억이 있네요.

서버 팀원들에게 토큰 재발급 API 호출시, 내려오는 error response들의 문서를 요청하고, 하나씩 검토하며 원인을 찾아갔습니다.

 

여러 원인 중 statusCode 401일 경우에 토큰이 만료된다는 경우를 발견하였고, 현재 상황에 대입하여 생각해 보았습니다.

 

스밈 프로젝트는 소셜로그인을 통해 로그인을 성공한 유저일 경우, 서버로부터 access, refresh token을 응답값으로 받게 됩니다. 모든 API 통신은 access를 헤더에 담아 요청을 해 왔으며, access의 만료 시간이 짧다는 점을 감안하여서 스플래시 뷰에 진입시 서버로부터 토큰을 재발급받는 API를 호출하도록 구현해 놓았습니다.

access와 다르게 refresh는 만료 시간이 더 길었으며, 스플래시 뷰에 진입시 refresh 토큰을 통해 토큰을 재발급받고, 기존 access 토큰을 재발급받은 토큰으로 갱신해 주는 로직으로 구현이 되어 있었습니다.

 

사진으로 표현하자면 이러한 플로우로 구현을 해 놓았습니다.

출처 : https://www.rfc-editor.org/rfc/rfc6749.html

 

하지만 여기서 간과한 점은, refresh가 만료되었을 때의 경우를 처리하지 않았다는 점이었습니다.

현재 저희 프로젝트는 access는 2시간, refresh는 2주로 만료 시간이 정해져 있었고, 2주가 지난 시점에서 refresh 토큰이 만료되었을 때, 서버에서 401 토큰 만료 에러를 던져 주었을 때의 처리가 제대로 되어 있지 않다는 것을 알게 되었습니다.

회원 탈퇴와 로그아웃 또한, 같은 이유로 에러가 발생했던 것이었습니다.

 

처음의 설계를 잘해야 하고, 토큰이 왜 access, refresh 두 개인지, 만료가 되었을 때 어떻게 해야 하는지 등

의문을 더 많이 가지고 접근했으면 방지할 수 있었을 에러였던 것 같아서 아쉬움이 느껴졌습니다.

 

아무튼, 해당 문제를 해결하기 위해 refresh 토큰까지 만료되었을 때는 유저가 다시 새로운 토큰을 발급 받아야 하기 때문에, 유저를 처음 시작 화면으로 보내 주는 플로우를 추가해 주었습니다.

 

기존 코드에서는 에러 발생시 토스트 메시지를 띄워 주고, 그대로 앱이 멈춰 버렸지만

 

        output.errorResult
            .receive(on: DispatchQueue.main)
            .sink { [weak self] error in
                self?.showToast(toastType: .smeemErrorToast(message: error))
                self?.restartSubject.send(())
            }
            .store(in: &cancelBag)

 

restartSubject라는 publisher를 추가해서, 에러 발생시 시작 화면으로 보내는 플로우를 추가했습니다.

refresh token이 만료되었을 때, 다시 토큰을 갱신할 수 있게끔 구현 로직을 수정했고, 더불어 회원탈퇴와 로그아웃 요청에 실패하는 오류도 같이 해결할 수 있었습니다.

 


 

토큰 만료와 같은 문제는 개인 프로젝트를 통해서는 겪을 수 없는 문제였는데, 실제 서비스를 운영하고, 유저들의 의견을 받다 보니 여러 상황을 겪어 볼 수 있는 것 같습니다.

개인적으로 초기 설계를 잘했으면 방지할 수 있었을 상황이었다고 생각했지만, 하나 배웠다는 마인드로 다음에는 꼭 짚고 넘어가고자 합니다.

 

다시 한번 에러 핸들링 환경을 구축해 놓는 것은 정말 중요하다는 생각이 드네요.

에러가 발생했을 때 그대로 앱이 멈춰 버리는 것이 아닌, 서버 요청을 여러 번 더 해 보는 combine operator들에 대해서도 공부해 보고 적용해 보고 싶다는 생각도 들었습니다.

 

지금 가장 필요하다고 생각이 들었던 건 firebase crachlytics입니다.

이번 일을 계기로 실서버에서의 에러 원인을 찾는 것에서 어려움을 느꼈고, 정말정말 중요한 사항이라고 생각을 해서 다음에 꼭 적용해 보고 블로그로 기록하는 것을 목표로 하고 있습니다.

Comments