[프로젝트 회고] 첫 로그인 기능 구현과 Spring Security 고민
들어가며
NBE5-7-2-Team07 프로젝트에서 처음 맡았던 큰 기능 중 하나는 로그인 기능이었다.
Spring Security와 JWT를 사용해 인증 흐름을 구현했고, RefreshToken을 어떻게 다룰지 고민했다.
당시에는 Security 설정 하나하나가 낯설었고, Filter와 EntryPoint, 토큰 발급 흐름을 연결하는 것도 쉽지 않았다.
그래도 이 작업을 통해 인증 기능의 기본 흐름을 직접 경험할 수 있었다.
구현한 기능
초기 로그인 기능에서 구현한 내용은 다음과 같다.
- Spring Security 설정
- 로그인 API
- JWT AccessToken 발급
- RefreshToken 발급
- RefreshToken 저장
- 로그아웃 처리
- 인증 실패 응답 처리
- 테스트 코드 작성
로그인은 단순히 아이디와 비밀번호를 확인하는 기능이 아니었다.
로그인 성공 후 토큰을 발급하고, 이후 요청에서 토큰을 검증하고, 토큰이 만료되면 재발급하고, 로그아웃 시 토큰을 정리하는 전체 흐름이 필요했다.
RefreshToken Entity 고민
PR을 작성하면서 이런 고민을 남겼다.
1
RefreshToken 엔티티를 조회하지 않는데 굳이 Entity가 필요할까?
처음에는 RefreshToken을 저장해야 한다는 생각으로 Entity를 만들었다.
하지만 실제 사용 흐름을 보면 저장만 하고 조회가 적거나, 삭제만 하는 상황도 있었다.
이때부터 “데이터를 저장한다”와 “도메인 엔티티로 다룬다”는 것이 항상 같은 말은 아니라는 생각을 하게 되었다.
RefreshToken은 인증 정책에 따라 DB에 저장할 수도 있고, Redis에 저장할 수도 있고, Blacklist 방식으로 관리할 수도 있다.
중요한 것은 프로젝트의 보안 요구사항과 운영 환경에 맞는 저장 전략을 선택하는 것이다.
로그아웃 처리 고민
로그아웃에서도 고민이 많았다.
- 헤더에 남아 있는 AccessToken은 어떻게 할 것인가?
- RefreshToken Cookie는 어떻게 삭제할 것인가?
- 서버에 저장된 RefreshToken은 삭제해야 하는가?
- 로그아웃 이후 재사용 공격을 어떻게 막을 것인가?
AccessToken은 발급 후 만료 시간까지 유효한 구조라서 서버가 즉시 무효화하려면 별도 저장소나 Blacklist가 필요하다.
반면 RefreshToken은 서버에서 관리하면 삭제 처리가 가능하다.
이 흐름을 직접 구현하면서 로그아웃은 단순히 클라이언트에서 토큰을 지우는 것이 아니라, 서버의 토큰 상태 관리와 연결되어 있다는 것을 배웠다.
CustomAuthenticationEntryPoint 고민
인증 실패 처리에서도 고민이 있었다.
CustomAuthenticationEntryPoint의 commence와 JwtTokenizer의 parse 과정에서 기능이 중복되는 것 같았다.
이때 느낀 점은 Security 흐름에서는 예외가 어디에서 발생하고 어디에서 응답으로 바뀌는지 명확히 알아야 한다는 것이다.
Filter에서 토큰을 파싱하다가 예외가 발생할 수 있고, 인증 객체가 없어서 EntryPoint로 넘어갈 수도 있다.
이 흐름을 이해하지 못하면 에러 응답이 중복되거나, 클라이언트가 이해하기 어려운 응답을 받을 수 있다.
테스트 작성
이 로그인 기능에서는 테스트 코드를 작성하고 수행했다.
처음에는 Security 테스트가 어렵게 느껴졌다.
일반 Service 테스트와 달리 인증 흐름은 Filter, Token, Cookie, Header 등 여러 요소가 함께 움직이기 때문이다.
그래도 테스트를 작성하면서 로그인 기능이 어떤 단계로 구성되어 있는지 더 잘 이해할 수 있었다.
테스트를 통해 확인한 것은 단순히 성공 여부가 아니라, 내가 설계한 인증 흐름이 예상대로 이어지는지였다.
배운 점
첫 로그인 기능 구현에서 배운 점은 많았다.
- Spring Security는 설정만 복사해서 쓰면 안 되고 흐름을 이해해야 한다.
- JWT는 발급보다 생명주기 관리가 더 중요하다.
- RefreshToken 저장 전략은 보안 정책과 연결된다.
- 로그아웃은 클라이언트와 서버 양쪽의 상태 정리가 필요하다.
- 인증 예외는 클라이언트가 이해할 수 있게 구분해야 한다.
당시에는 코드 컨벤션과 메서드명도 고민이 많았다.
하지만 그런 고민을 PR에 남기고 리뷰를 요청한 것도 좋은 경험이었다.
마무리
이 로그인 기능 구현은 이후 JWT와 Cookie 트러블슈팅을 이해하는 기반이 되었다.
처음부터 완벽하게 구현하지는 못했지만, 인증 기능이 얼마나 많은 요소로 이루어져 있는지 직접 경험할 수 있었다.
앞으로 인증 기능을 만들 때는 단순히 “로그인 된다”에서 멈추지 않고, 토큰 저장, 재발급, 로그아웃, 예외 응답, 테스트까지 하나의 흐름으로 설계해야겠다.
Leave a comment