개발놀이터

Redis를 이용해 세션 구현하기 (with Spring) 본문

CS 지식/데이터베이스

Redis를 이용해 세션 구현하기 (with Spring)

마늘냄새폴폴 2023. 5. 3. 03:09

저번 포스팅에선 Redis를 이용해 캐싱을 구현해봤습니다. 

 

https://coding-review.tistory.com/365

 

Redis를 이용해 캐싱 구현하기 (with Spring)

저번 포스팅에선 Redis의 기본적인 개념에 대해서 알아봤습니다. Redis가 어떻게 NoSQL중에서 가장 빠른 성능을 보여줄 수 있었는지, 자료구조는 어떤 것을 지원하는지, 사용처는 어떤게 있는지, 배

coding-review.tistory.com

 

이번 포스팅에선 Redis를 이용해 세션을 구현해보도록 하겠습니다. 설정이나 사용하는 방법에 대해서는 위의 포스팅을 참고해주시면 감사하겠습니다. 

 

사실 Redis로 세션을 구현하는 것은 정말정말 간단합니다. 하지만 너무 간단하기 때문에 재미가 없습니다. 따라서 이번 포스팅에선 먼저 간단한 구현을 알아보고 특정한 상황을 가정하고 진행해보도록 하겠습니다. 

 

우선 의존성을 추가해줘야합니다. 

implementation 'org.springframework.session:spring-session-data-redis'

 

그리고 컨트롤러를 만들어주면?

import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RedisSessionController {

    @GetMapping("/create_session")
    public String createSession(HttpSession session, @RequestParam("name") String name) {
        session.setAttribute("name", name);
        return "create success";
    }

    @GetMapping("/check_session")
    public String checkSession(HttpSession session) {
        String name = (String) session.getAttribute("name");
        return name;
    }
}

 

끝입니다. 

 

이제 해당 URL로 접속해서 session을 만들고 조회를 해보면 session값이 잘 저장되는 것을 볼 수 있습니다. 

 

http://localhost:8080/create_session?name=ks

 

http://localhost:8080/check_session

너무 간단하다!

이렇게 값이 잘 나오고 데이터베이스에 가보면?

값도 잘 저장된 것을 볼 수 있습니다. 

 

끝입니다!

 

정말 너무 간단하지 않나요? 저도 처음에 너무 간단해서 어안이 벙벙했습니다...

 

이렇게 Redis에 세션을 넣어서 구현해봤는데요. 그냥 HttpSession을 이용해 구현하는 것과 Redis를 이용해 세션을 구현하는 것에 차이가 있습니다. 

 

1. 서버가 내려가더라도 세션이 살아있다.

우선 기존에는 WAS를 내려버리면 세션값이 사라지는 현상이 있었습니다. 때문에 서버를 내리고 올릴때마다 다시 로그인했어야했죠. (토이프로젝트 할 때 겁나 귀찮았습니다)

 

하지만 Redis를 이용해 세션을 구현하면 서버를 내리더라도 Redis에 세션값이 저장되어 있기 때문에 세션이 유지가 됩니다. 

 

보통 세션을 처음 공부하면 이런 의문이 드는데요. 바로 session.getAttribute("name"); 이라고 구현하면 사용자A도 해당 코드를 탈 것이고, 사용자B도 해당 코드를 타는데 어떻게 둘이 다른 값을 가지고 있지? 라는 궁금증이 듭니다. 

 

세션은 서버에 저장할 때 사용자ID, 언제 세션이 만들어졌는지, 사용자의 IP등을 같이 저장하기 때문에 다른 값을 반환받는 것입니다. 

 

Redis에 세션을 저장하는 것도 비슷한 방식입니다. 잘 보시면 sessionAttr에 값이 저장되고, lastAccessTime과 creationTime을 저장해 사용자를 판별하는 모습을 보여주죠. 

 

2. 로드밸런싱에서도 유용하다

또한 Redis를 이용하면 서버를 여러개 두고 트래픽을 관리하는 로드밸런싱에도 장점이 있습니다. 

 

만약 8080으로 들어온 사용자와 8081로 들어온 사용자가 세션을 만들었다고 가정해보면 실제로 F12를 눌러서 확인해보면 이 둘의 세션아이디가 다릅니다. 이러면 잘못된 세션에 저장하나마나 계속 새로운 세션을 만드는겁니다. 

 

이런 상황에서 Redis를 사용하면 같은 세션값을 보장해줍니다. 이를 Redis Clustering이라고 하더군요. 하지만 데이터베이스 튜닝 방식중 하나인 클러스터링과 헷갈려서 저는 썩 좋은 표현은 아닌 것 같습니다. 

 

아무튼 Redis를 사용해 세션을 구현하면 장점이 꽤 많기 때문에 정말 많이 애용할 것 같습니다. 

 

사용자 인증을 하는 방법에는 크게 Redis + Session / JWT 인증토큰 이렇게 두가지가 있다고합니다. 

 

Redis + Session은 Stateful 프로토콜이구요. JWT 인증토큰은 Stateless 프로토콜이라고 합니다. 

 

그렇기 때문에 Stateful 과 Stateless 에서 적용되는 장단점을 그대로 가지고 있습니다. 

 

이번 포스팅이 너무 짧았기 때문에 막간을 이용해 Stateful 과 Stateless의 장단점을 보도록 하죠. 

 

Stateful VS Stateless

*Stateful

Stateful은 현재 세션에 다음 트랜잭션에서 필요한 정보를 가지고 있는 경우를 말합니다. 때문에 클라이언트는 가지고 있어야할 데이터의 양이 적고 서버가 가지고 있어야할 데이터가 많죠. 

 

보통 하나의 세션에 데이터가 이어져야하는 온라인뱅킹이나 SMTP에서 주로 사용합니다. 

 

하지만 이런 Stateful의 특징 때문에 확장성이 떨어지고 멀티태스킹에 능하지 못하다는 단점이 있습니다. 이러한 단점은 

MicroService Architecture(이하 MSA)를 채택한 프로젝트에서는 알맞지 못한 방식입니다. 

 

하지만 방금 보셨다시피 구현하기가 굉장히 쉬워서 개발자 입장에서는 굉장히 좋습니다. 

 

*Stateless

Stateless는 Stateful과 다르게 현재 세션에 다음 트랜잭션에서 필요한 정보를 가지고 있지 않는 경우를 말합니다. 때문에 클라이언트는 가지고 있어야할 데이터의 양이 많고, 서버가 가지고 있어야할 데이터의 양이 적은 프로토콜이죠. 

 

Stateful과 다르게 확장성과 멀티태스킹에 굉장히 용이하고 때문에 많은 서비스가 Stateless 즉, 무상태로 개발되었습니다. 우리가 가장 많이 사용하는 HTTP부터 DNS, SMS가 바로 무상태로 설계된 프로토콜입니다. 

 

JWT가 Stateless라고 말했었죠. 때문에 JWT는 확장성이 극대화된 MSA에서 알맞은 서비스입니다. 하지만 이런 확장성과 별개로 구현하기가 굉장히 까다롭다는 단점이 있는데요. 

 

항상 refresh token과 access token을 관리해주어야하고, JWT 토큰을 대충 사용했다간 보안상으로 굉장히 취약해질 수 있습니다. 

 

 

마치며

이번에 우리가 알아본 방식은 Stateful 프로토콜 중 하나인 Redis + Session을 이용해 사용자 인증을 구현해봤습니다. 매우 간단하니 여러분들도 자주 사용해보시면 좋은 경험을 얻을 수 있을 것 같습니다. 

 

긴 글 읽어주셔서 감사합니다. 오늘도 즐거운 하루 되세요~