백엔드 개발자 황시우의 블로그
cheimbus
백엔드 개발자 황시우의 블로그
  • 분류 전체보기 (3)
    • 프로젝트 (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

태그

백엔드 개발자 황시우의 블로그

cheimbus

프로젝트

[FITDAY] 인증 인가 개발기

2025. 5. 14. 15:51

게시: 2025/5/14

By: 황시우

개요

FITDAY에 인증 인가를 개발하는데 있어 관리자 로그인과 OAuth2.0 기반 소셜 로그인을 구현했습니다.
이 과정에서 Factory Method 패턴을 적용해 관리자 로그인, 서드파티 애플리케이션 로그인을 각각 독립적인 핸들러로 분리하였고, 새로운 로그인 방식을 쉽게 추가할 수 있도록 구조화했습니다.

이후 JWT를 발급해 RefreshToken을 Redis로 캐싱 했을때와 DB에 저장했을 때의 응답 속도를 비교 분석하여 캐싱 방식이 실제로 얼마나 성능을 개선하는지 구체적인 수치와 함께 다뤄봤습니다.

 

Factory Method 패턴이란?

  • 객체 생성 코드를 별도의 팩토리 클래스나 메서드로 분리하여, 객체 생성의 책임을 위임하는 디자인 패턴입니다.
  • 인터페이스나 추상 클래스를 정의하고 이를 구현한 클래스가 필요할 때 팩토리를 통해 생성합니다.

즉, 여러개의 서드파티 애플리케이션(Naver, Google 등)을 추가할 때 별도의 노력없이 쉽게 추가할 수 있습니다.

 

Factory Method 개요

구성 요소 역할
Product 생성될 객체의 인터페이스 또는 추상 클래스
ConcreteProduct Product 인터페이스를 구현한 실제 클래스
Creator Product를 반환하는 Factory Method 선언
ConcreteCreator Factory Method를 구체적으로 구현하여 ConcreateProduct 생성

 

FITDAY에 적용한 Factory Method 패턴 개요

구성요소 역할
Product AuthService, OAuth2AuthService
ConcreteProduct LocalAuthService (admin), KakaoAuthService (kakao)
Creator AuthServiceFactory
ConcreteCreator AuthServiceFactory에 주입된 AuthService, OAuth2AuthService 빈

 

Factory Method를 활용한 로그인 과정

우선 kakao로 소셜로그인 과정에 대해 설명해 드리겠습니다.

티스토리에서 코드블럭을 사용하면 코드가 잘 보이지 않아서 스크린샷으로 대체하였습니다.

 

Controller

 

Creator (Factory)

ConcreteProduct (kakao)

 

위 사진에서 kakao로 요청이 들어온다면, 팩토리를 호출하여 스프링 컨텍스트에 등록된 AuthService 구현체들 중 키가 kakao인 빈을 꺼내고 해당 빈을 OAuth2AuthService로 캐스팅하여 반환합니다.

(관리자 로그인과 소셜로그인을 분리하기 위해 OAuth2AuthService는 AuthService를 상속했습니다.)

 

이후 getAuthorizationUri 를 통해 리다이렉트 URI를 생성하여 반환합니다.

 

Controller

 

KakaoService

 

kakao develper에서 리다이렉트 URI를 설정해놓고, 사용자가 kakao 로그인 완료 시 설정된 callback URI로 인가코드를 전달받습니다.

이후 Factory Method 패턴에서 동일한 방식으로 kakao용 AuthService 빈을 가져와 authenticate 메서드를 호출합니다.

 

이 과정에서 kakao AccessToken을 발급받고 사용자 정보를 가져온 뒤, RefreshToken과 함께 DB에 저장하고 FITDAY 전용 JWT AccessToken을 생성해 클라이언트로 전달합니다.

 

추후에 Google을 적용하고자 한다면, GoogleAuthService 구현체만 추가한다면 빠른시간에 확장할 수 있습니다!

 

 

로그아웃 과정

사용자가 로그아웃을 한다면 어떻게 처리하는지 고민해 봤습니다.

두 가지 방안이 있는데,

 

1. AccessToken 블랙리스트 저장

블랙리스트로 저장하면 로그아웃 즉시 토큰 무효화를 할 수 있습니다.

따라서 보안에 장점이 있지만, 매 요청마다 조회 비용이 추가로 발생한다는 단점이 있습니다.

 

2. 짧은 TTL에 의존하기

이 방법은 AccessToken의 만료 시간을 1분 ~ 5분 정도로 짧게 설정하는 것입니다.

이후 로그아웃 시 클라이언트가 토큰을 즉시 버리도록 유도합니다. (localStorage.removeItem)

 

이 방법의 장점은 구현이 간단하지만 단점은 만료 전까지는 탈취된 토큰으로 요청이 가능하다는 점입니다.

 

FITDAY의 특성상 보안에 덜 민감한 콘텐츠 이므로 AccessToken 만료 시간을 5분으로 설정해서 사용하기로 결정하였습니다.

 

추후에 서비스를 보안해서 추가한다면 필요시 1번의 방법으로 리팩토링 할 예정입니다.


Redis 캐싱 vs DB 저장

테스트 목적

RefreshToken을 발급 후 Redis 캐시와 DB에 각각 저장했을 때, 로그인 API의 응답지연에 어떤 차이가 나는지 비교해 보겠습니다.

 

테스트 환경

모니터링 도구 인스턴스
Pinpoint API 서버 : t3a.small, Pinpoint 서버 : t3.medium
  • t3a.small => CPU 2코어, 2GB 메모리
  • t3.medium => CPU 2코어, 4GB 메모리

 

테스트 시나리오

FITDAY API에 요청을 보내 Redis 캐싱 방식과 DB 저장 방식으로 각각 처리한 뒤, Pinpoint-Agent로 응답 시간을 수집합니다.

 

DB 저장

 

 

위 사진에서 DB에 저장 했을때는 네트워크 요청은 차이가 없지만, 트랜잭션이 발생해 233 ms가 추가로 발생한 것을 확인할 수 있었습니다.

Redis 캐싱

 

Redis 캐싱, DB 저장 부하 테스트

 

최종적으로 DB에 저장한 경우에는 410 ms, Redis 캐싱한 경우에는 231 ms가 소요되어 응답 속도가 약 43.7 % 단축된 것을 확인 할 수 있었습니다!

 

마지막으로

조회 수 캐싱 전략, hot, recent 캐싱 전략을 거쳐 AccessToken 캐싱을 경험해 보았는데, 상황에 따라 캐싱을 적용하면 성능이 월등하게 높아진다는 것을 눈으로 확인할 수 있었던 경험이었습니다.

FITDAY 서버 개발을 마무리 하였는데, 앞으로 프론트를 공부하면서 필요한 기술들이 생기면 추가로 계속해서 개발을 할 예정입니다.

문제를 스스로 고민하고 해결하는 과정을 통해 개발자로서 자신감이 크게 향상되었고, 전반적으로 매우 의미있고 좋은 경험이었습니다.

 

참고

https://developers.kakao.com/docs/latest/ko/index

'프로젝트' 카테고리의 다른 글

[FITDAY] 99.98% 성능 개선 최적화 여정  (2) 2025.05.15
[FITDAY] CI/CD 자동화 여정기  (0) 2025.05.01
    '프로젝트' 카테고리의 다른 글
    • [FITDAY] 99.98% 성능 개선 최적화 여정
    • [FITDAY] CI/CD 자동화 여정기
    백엔드 개발자 황시우의 블로그
    백엔드 개발자 황시우의 블로그
    백엔드 개발자 황시우의 블로그

    티스토리툴바