본문 바로가기
ETC/System Design

MSA 기반 환경에서의 인증과 인가 - 1. 개요

by devson 2021. 5. 20.

서비스가 성장하고 서비스에서 다루는 도메인이 복잡해 짐에 따라 도메인 별로 서비스를 분해하여 각 도메인 간의 커플링을 느슨하게하고 도메인의 응집도를 높이며 이를 통해 빠르고 안정적인 개발이라는 장점을 취하기 위해 MSA를 행하는 곳이 많아졌다.

 

그리고 내가 속한 조직 역시 기존 monolithic 환경에서 MSA로 이전하는 작업을 진행 중이고 그 중에서 나는 사용자와 인증/인가 관련 서비스를 작업하였다.

 

이 포스팅은 MSA 환경에서 인증/인가를 구현하면서 어떤 식으로 시스템을 구축하였고 어떤 고민을 하였는지에 대해 정리하는 글이다.

 


 

웹 서비스에서 크게 Session 또는 JWT(JSON Web Tokens)기반의 Access Token을 통해 Security를 구현한다.

MSA 환경에서 인증과 인가에 대해 알아보기 전 이 두 방식을 비교해보자.

Session

Session 기반의 Security를 적용하는 경우 손쉽게 구현이 가능하지만 Session 데이터는 서버 애플리케이션 메모리에 저장되기 때문에 실제로 프로덕션 환경에서 여러 대의 서버 인스턴스를 운용할 경우 Session 기반 Security는 따져야할 것이 많다.

 

Session을 사용하면서 여러 대의 서버 인스턴스를 운용할 때 크게 2가지 기법을 사용한다.

Sticky Session

Load Balancer에서 Cookie를 사용하여 특정 Client를 특정 서버로만 요청을 보내도록 할 수 있다.

Sticky Session

이러한 방식을 Sticky Session 이라하며 기존 서버 애플리케이션의 설정을 변경하지 않고도 여러 대의 서버를 운용할 수 있다는 장점이 있다.

 

하지만 특정 서버 인스턴스가 갑작스런 장애를 겪는다면 어떻게 될까?

Session이 연결된 서버 인스턴스가 장애를 겪는다면?

Load Balancer는 똑똑하게 응답하지 않는 서버 인스턴스로 요청을 보내지 않고 응답할 수 있는 다른 서버 인스턴스로 요청을 보낼 것이다.

하지만 해당 서버 인스턴스는 클라이언트의 세션 데이터를 갖고 있지 않기 때문에 기존 세션은 유실된다.

앞서 예시로 살펴본 단순 장애의 상황 뿐만 아니라 서버 애플리케이션 업데이트 등의 서버 애플리케이션이 내려갈 수 있는 여러 상황을 고려했을 때 서버 인스턴스 메모리에 세션 데이터를 갖고 있는 것은 매우 불안정하다.

Session Clustering

Session 데이터를 서버 인스턴스 메모리에 저장하지않고 외부 공유 저장소에 저장하면 어떨까? 그러면 서버 인스턴스가 갑작스럽게 내려가더라도 Session을 유지할 수 있을 것이고 또 그 덕에 Load Balacer는 서버에 트래픽을 고르게 분산시킬 수 있을 것이다.

Session을 서버 인스턴스 메모리에 저장하는 것이 아니라 외부 Session Storage에 저장하여 서버간 Session을 공유할 수 있는 방식을 Session Clustering 이라고 한다.

 

Session 데이터가 외부에 저장되기 때문에 앞서 살펴본 서버 인스턴스 메모리에 Session 데이터를 들고 있을 때의 단점을 보완할 수 있다.

하지만 이 경우 매 요청마다 Session Storage와 통신이 필요하게 되고 트래픽이 몰리게 될 경우 이는 IO 병목 현상을 일으키거나 SPOF가 될 수 있다.


위와 같은 이유로 프로덕션 환경에서 Session 기반의 Security는 신경써야할 것이 많고 여러 서비스를 독립적으로 운용해야하는 MSA 환경에서 Session을 핸들링하는 코드의 중복이 여럿 생길 수 밖에 없다.

(물론 신경쓸 점이 많다는 것이지 Session 방식이 안좋다는 것은 아니다)

 

Access Token (JWT)

Client가 서버로부터 발급받은 Access Token을 담아(주로 Request header에) 요청을 보내면 서버에서는 해당 토큰을 검증하여 해당 요청을 처리할 것인지를 판단한다.

Access Token이 JWT 기반이라면 서버는 토큰을 발급할 때 사용한 Secret만 알고 있다면 빠르게 해당 토큰에 대한 유효성을 검사할 수 있다.

 

Session에 비해 토큰 발급, 유효성 검사, 또는 서버에서 클라이언트 강제 로그아웃 처리 등은 추가적으로 작업이 필요하다는 단점이 있지만 여러 서버를 운용할 때 클라이언트에 대한 인가 처리를 비교적 쉽게 처리할 수 있다.

(또한 Session과 같이 Cookie를 사용하지 않기 때문에 CSRF에 대한 걱정도 덜 수 있다)

 


 

나는 MSA 환경에서 많이 사용되고 서버에서 Security 관련하여 가장 많이 하게 될 클라이언트에 대한 인가 처리가 서비스 운용에 있어 문제 사항이 되지 않게하기 위해 JWT 기반의 Access Token을 사용하여 Security 시스템을 구성하였다.

 

MSA 환경에서의 JWT를 기반의 Security 시스템 아키텍쳐 Overview는 다음과 같다. (세부 구성은 시스템 별로 다를 수 있다)

 

 

  1. Client는 발급 받은 Access Token을 담아 API Gateway로 요청을 보낸다
  2. API Gateway는 Authorizer를 통해 Access Token이
    • 해당 서비스에서 발급된 것이 맞는지 (secret 확인)
    • 해당 Access Token의 만료기간이 지났는지
    등을 확인한다
  3. Access Token이 서비스에서 발급된 것임이 확인된 경우 요청에 맞는 Resource Server로 요청을 보낸다

 


 

서비스가 독립적으로 운용되는 MSA 특성 상 요청 인가 기능을 각 서비스에게 모두 맡기는 것이 아니라 Client와 맞닿는 API Gateway가 해당 요청에 대한 인가를 처리하고 유효한 요청이라면 해당 요청을 각 Resource Server로 라우팅하는 식으로 시스템을 구성한다.

참고:

https://microservices.io/patterns/security/access-token.html

https://bcho.tistory.com/794

https://www.samsungsds.com/kr/insights/1239180_4627.html

댓글