MSA 전환시, 세션 유지를 위한 방법들..

이상현·2023년 3월 6일
0

차곡차곡

목록 보기
6/8
post-thumbnail

Monolithic → MSA 전환

회사에서 프로젝트를 진행하면서, Monolithic 구조로 되어있는 시스템을 MSA 구조로 전환하는 프로젝트를 진행하였습니다.

기존의 시스템은 오랫동안 운영/유지보수 되고있던 대형 프로젝트였고, 복잡한 비즈니스 로직과 서비스들간의 결합도가 강한 상태였습니다.

위와같은 이유로 MSA 전환에 여러 어려움이 있었지만, 그 중에서도 인증/인가 관련된 이슈를 해결하려했던 경험을 정리해보려고 합니다.

JWT 토큰을 통한 인증/인가

MSA 환경에서는 서로 다른 서비스 POD 또는 같은 서비스 내의 scale-out된 다른 POD 간의 인증/인가 정보를 유지하기 위해서 JWT 토큰을 기반으로한 인증방식이 주로 사용됩니다.

이번 프로젝트에서도 기존의 로그인 영역을 하나의 독립된 서비스로 분리해내면서 JWT 토큰 방식을 사용하여 인증/인가정보를 공유하였습니다.

문제 상황 1

세션방식을 유지해야하는 제약조건 발생

JWT토큰을 이용하여 대부분의 서비스에서 인증/인가 정보가 잘 공유되었는데, 비즈니스 검증 테스트에서 문제가 발생했습니다.

비즈니스 로직 내부에, 사용자의 세션스토리지를 이용한 로직이 얽혀있었던 것이 문제가 되었습니다.

위 문제를 해결하기 위해 세션스토리지에 저장되는 데이터들을 JWT토큰 또는 DB에 저장하는 것이 바람직하였으나,
발생할 SideEffect 로 인한 위험성이 예측이 안되는 상황이었습니다.
결국, 해당 업무를 위해 세션을 일부 서비스에서 유지하는 것으로 의사결정이 되었습니다.

문제 상황 2

Scale-Out 시 세션끊김 발생

문제상황1로 인해 프로젝트에는 JWT + 세션 방식으로 인증/인가 정보를 유지하게 되었습니다.
(어딘가 찝찝한 상태이지만 당시에는 별다른 선택지가 없는 상황...)

얼마 후, Infra팀에서 전체서비스에 대해 부하테스트를 실시하였습니다.
일정 트래픽 이상이 되면 Scale-Out 되도록 설정되어 있었기에 테스트를 통과할 줄 예상했는데, 찝찝했던 곳에서 문제가 발생하였습니다.

문제의 원인은 유지되고 있었던 Session 때문에 발생하였습니다.

단일 Pod로 서비스를 제공할때는 문제가 되지않다가,
Scale-Out으로 Pod가 여러개가 되자 Session이 공유되지 않는 것이 문제의 원인이었습니다.

조치1

Sticky Session

"Session방식을 걷어내지 않는다." 라는 제약조건이 있었기에, Session을 유지하면서 문제를 해결할 방법을 찾아야 했습니다.

급한대로 프로그램에 크게 변경을 주지 않으면서, 문제를 해결할 수 있는 방법으로 StickySession 을 적용하였습니다.

StickySession 이란 사용자가 접속했던 Pod의 정보를 기억하도록 한 후,
이후 동일한 사용자의 새로운 요청 시, 이전과 동일한 Pod로 요청을 보낼 수 있도록하여 세션정보를 유지하는 방법입니다.

인프라 단에서의 설정변경으로 적용이 가능하였기에, 코드의 큰 변화없이 빠르게 적용할 수 있었지만, StickySession을 적용함으로써 MSA의 로드밸런싱 측면에서는 손해를 보게되었습니다.

StickySession은 아래와 같은 단점을 가지고 있습니다.

  • 로드밸런싱이 잘 동작하지 않을 수 있다.
  • 특정 서버만 과부하가 올 수 있다.
  • 특정 서버 Fail시 해당 서버에 붙어 있는 세션들이 소실될 수 있다.

조치 2

Session Clustering

MSA 적용의 이점을 살리기 위해서는 새로운 방법을 찾아 적용했어야 했습니다.
그렇게 여러 방법들을 알아보던 중, Redis를 이용한 Session Clustering 방식을 적용하기로 결정하였습니다.

세션 정보를 서버에서 직접 관리하지않고, 외부 Redis에 저장하고 각각의 Pod에서는 이를 참조하게하여 모든 pod에서 세션정보를 공유하도록 하는 방식이었습니다.

프로젝트에 Redis SessionClustering을 적용하기 위해, 코드의 수정이 필요했지만, SpringBoot에서 의존성 추가와 몇가지 설정을 수정하면 비교적 간단하게 적용할 수 있었습니다.

그밖에 다른 문제들..

  • Redis 직렬화/역직렬화 이슈

    Redis를 적용하는 과정에서 직렬화/역직렬화로 인한 에러를 마주하게 되었습니다.
    Redis에 저장한 데이터객체가 타 마이크로서비스에 존재하지 않아 역직렬화시에 문제가 발생했던 것입니다.

    이미 대부분의 마이크로서비스에서는 JWT 토큰방식으로 인증/인가 정보를 공유하여도 문제가 없었기에, Session 방식 유지가 필요한 서비스에서만 클러스터링을 적용하도록 한정하여 문제를 해결할 수 있었습니다.

  • Redis세션클러스터링 사용시 고려해야할 점

    Redis에 세션서버를 구성하기에, 모든 세션정보들이 하나의 서버에 저장되게 됩니다.
    이때, 어떠한 이유로 인해 Redis 서버에 장애가 발생하면, 모든 세션이 사라지게 되는 문제가 발생할 수 있습니다.
    이와같은 상황을 방지하기위해 필요시 Redis 서버도 다중화하는 것도 고려해보아야 합니다.



참고자료

profile
'당신을 한 줄로 소개해보세요'를 이 블로그로 대신 해볼까합니다.

0개의 댓글