순간을 성실히, 화려함보단 꾸준함을

wsl+docker 를 사용한 spring boot + Redis 사용하기!! 본문

나의 개발 메모장

wsl+docker 를 사용한 spring boot + Redis 사용하기!!

폭발토끼 2023. 6. 11. 15:42

안녕하세요

벌써 글또 프로그램이 마지막을 향해서 달려가고 있습니다.

 

앞으로 총 4번의 활동만 남았는데요 ㅎㅎ 항상 처음보단 마지막이 중요하다고 생각하기 때문에 끝까지 완주를 하기 위해 노력하려고 합니다.

 

글또 9번째 글인 오늘의 주제는 spring boot 와 redis 를 연동했던 과정을 적어보려고 합니다.

 

배경

현재 토이 프로젝트를 진행하는데 있어서 jwt 를 사용하여 로그인 기능을 구현하고 있습니다.

accessToken 으로 인증 절차를 처리하고 있고 accessToken 이 만료되었을때 이를 갱신시켜줄 수단으로 refreshToken 을 사용하고 있습니다.

이때 refreshToken 을 사용하여 accessToken 을 갱신시켜주려고 할때 서버쪽에서도 어딘가에 refreshToken 을 가지고 있어야지만 올바른 refreshToken 을 가지고 있는지 확인할 수 있고, 만료시간이 지나지 않은 refreshToken 인지 확인을 할 수 있겠죠?

 

가장 간단하게 DB 에 저장하는 방식을 고려해보았습니다. RefreshToken 의 만료시간과 함께 DB 에 저장한다면 요청이 올때마다 확인한 뒤 만료가 되었다면 DB 에서 삭제해도 되겠죠??

그렇지만 이 방법은 최선의 선택이 아니라고 생각이 들었습니다. 이유는 요청할때마다 확인 하는 것이 매우 비효율적인 방법이라고 생각했기 때문입니다.

수많은 유저들이 이용하는 시스템이라고 생각할때 엄청나게 많은 request 가 발생할 것이고 매번 DB I/O 작업을 거치게 된다면 그 부하를 감당하기에 쉽지 않을 것 이기 때문입니다.

 

그래서 많은 글들을 참고해보시면 아시겠지만 Redis in-memory DB 방식을 사용하였습니다.

서버의 메모리를 사용하는 방법이 아니라 휘발성 메모리인 RAM 에 저장하는 방식이라 DB I/O 도 발생하지 않는 장점이 존재합니다.

( Redis in-memory DB 는 영구적으로 저장할 수 있는 방법이 존재합니다!!![REDIS] 📚 캐시 데이터 영구 저장하는 방법 (RDB / AOF) (tistory.com))

 

그래서 어떻게 Redis 를 spring boot 에 적용시켰는지 그 과정을 하나씩 기록해볼 예정입니다.

 

과정

환경은 아래와 같습니다.

 

OS : window 10

linux : Ubuntu(20.04) + wsl

framework : spring boot 2.7.6

docker desktop

 

1. wsl 활성화 시키기

저의 컴퓨터는 현재 윈도우이기 때문에 docker 를 사용해 redis 서버를 띄우기에는 제약이 따릅니다. 그렇기 때문에 윈도우에서 지원해주는 wsl 을 사용하여 docker 를 활성화 시키기로 하였습니다.

 

윈도우 [검색] 버튼을 클릭 후 windows 기능 켜기/끄기 버튼을 클릭하면 위와 같은 창이 뜨고 빨간색 네모 박스로 표시한 'Linux용 Windows 하위 시스템' 을 체크해준 뒤 재부팅을 실행합니다.

 

그 후 microsoft store 에 들어가서 Ubuntu 를 설치해주어야 합니다.

아이디/비밀번호를 설정하는 것은 잊지마시고 잘 입력해주세요!!

 

powershell 을 관리자 권한으로 실행 시킨 후 Ubuntu 가 잘 설치되었는지 확인해줄까요?

wsl -l -v

위 명령어를 입력하여 설치한 Ubunt 의 정보를 알 수 있는데 현재 저는 wsl2로 upgrade 를 실행하여서 version : 2 로 나오지만 아마 upgrade 를 해주지 않은 상태라면 1이라고 나올 것 입니다.

 

docker 에서 wsl 을 사용하기 위해서는 wsl 버전이 반드시 wsl2 이어야 합니다. 따라서 아래 링크로 들어가 해당 패키지를 설치해주도록 합시다.

이전 버전 WSL의 수동 설치 단계 | Microsoft Learn

 

이전 버전 WSL의 수동 설치 단계

wsl install 명령을 사용하지 않고 이전 버전의 Windows에 WSL을 수동으로 설치하는 방법에 대한 단계별 지침입니다.

learn.microsoft.com

위의 링크에 들어가서 패키지를 설치해 준 뒤 version을 2로 설정해줍시다.

wsl --set-default-version 2

만약 위의 명령어를 입력했음에도 불구하고 version이 여전히 1이라면 아래 명령어를 입력해주세요

(전 아래 명령어를 입력해서 version 을 변경하였습니다)

wsl --set-version Ubuntu-20.04 2

정상적으로 wsl 이 설치되었고 version 도 2로 변경되었으면 powershell 에서 wsl 이라고 입력하면 익숙하게 보시는 리눅스 환경의 cli 를 보실 수 있으실 겁니다.

 

2. docker desktop 설치

wsl 설정이 끝났으면 이제 docker 를 설치해봐야겠죠??

Get Started | Docker

 

Get Started | Docker

Get started with Docker Desktop and join millions of developers in faster, more secure app development using containers and beyond.

www.docker.com

위 링크에 들어가 docker desktop 을 설치해 줍시다.

docker desktop 을 실행시켜준 뒤 설정에 들어가 위에 해당하는 목록을 체킹 해줍시다.

그리고 사용가능한 wsl 이 있는지 확인해줍시다. 만약에 위와 같이 Ubuntu-20.04 라는 wsl 이 목록에 존재하지 않는다면 wsl 의 version 을 다시 한번 확인해보세요!!! 만약 여전히 1 이라면 목록에 노출이 되지 않을거고 docker 를 띄우지 못할겁니다!

 

정상적으로 docker 를 사용할 수 있는지 확인해봐야겠죠?

docker -version

powershell 에 위 명령어를 입력해줍시다!

 

3. redis image 다운

wsl 에 docker 까지 띄웠다니!!! 다들 조금만 힙냅시다 ㅎㅎ

이제 목표인 redis 를 docker 서버에 띄워야 하니 먼저 redis image 를 docker 에서 다운 시켜 줍시다!!!

 

먼저 powershell 에서 wsl 명령어를 통해 리눅스 환경으로 들어가 주시고 redis image 를 다운!!

$ docker pull redis

다운이 전부 완료가 되면 image 를 실행시켜줍니다

$ sudo docker run -p 6379:6379 redis

정상적으로 pull 을 받고 run 을 시켰으면 docker desktop 에서 확인했을 시에 위와 같이 status 가 Running 이라고 뜰겁니다.

$ docker ps

위 명령어로 실제로 컨테이너가 실행중인지 확인해 볼까요?

잘 작동중이네요 ㅎㅎㅎ

 

참고로 실행 중 이지 않은 컨테이너 까지도 확인하고 싶으시면 아래 명령어를 입력해서 확인해보시면 됩니다.

$ docker ps -a

 

4. spring boot 에서 Redis 사용해보기

 

spring boot 프로젝트에 redis 를 적용하기 전에 docker 컨테이너에서 redis 에 접속해보도록 할까요?

$ docker exec -it redis /bin/bash

위와 같이 wsl 에서 docker 컨테이너로 접속하였고 이제 redis 에 접속해 보도록 하겠습니다.

/data# redis-cli

IP:Port > 

로 변경된 것을 확인할 수 있죠???

여기서부터는 Redis 명령어를 통해서 여러 정보들을 확인할 수 있는데 이에 대해서는 역시 Redis 공식 docs 를 참고해주시면 될 것 같습니다. (굉장히 친절하게 잘 알려주고 있습니다)

Documentation | Redis

 

Documentation

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker

redis.io

이제 redis 라이브러리를 spring boot에 추가해 줍시다.

gradle 에 해당 의존성을 추가해주었습니다.

dependencies {
    ...

//    redis
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}

그 후에 어느 port 로 연결해줄지 cache 를 사용할지 안할지 어떤 host 를 사용할지 등 정의를 해주어야 합니다.

application.yml 파일에서 설정해 줍시다.

spring:
    redis:
      host: localhost
      port: 6379

자 그러면 여기까지 무탈히 잘 왔으면 redis in-memory  db 를 사용할 수 있습니다 ㅎㅎ

고생하셨습니다.

 

Redis에 refreshToken 사용하기

이제 본격적으로 refreshToken 을 redis 메모리에 저장해보도록 하겠습니다.

spring boot 에서 redis 를 사용하는 방법은 공식문서가 굉장히 상세히 잘 나와있더라구요.

그래서 저는 공식문서로만으로도 구현하는데 큰 문제가 없었습니다.

 

Spring Data Redis

 

Spring Data Redis

Some commands (such as SINTER and SUNION) can only be processed on the server side when all involved keys map to the same slot. Otherwise, computation has to be done on client side. Therefore, it is useful to pin keyspaces to a single slot, which lets make

docs.spring.io

먼저 RefreshToken Entity 를 생성해 줍시다.

@RedisHash 어노테이션을 RefreshToken entity 에 붙여주고 value 와 timeToLive 옵션을 설정해 주었습니다.

일단 임시적으로 유지시간을 1 hour (3600 second) 로 설정하였습니다.(timeToLive 의 역할입니다)

 

@RedisHash 가 의미하는 바가 무엇일까요?
- Redis 를 사용하는 애플리케이션 객체를 Redis 데이터에 매핑시켜주는 역할을 수행하는 어노테이션입니다.

RedisTemplate 과 RedisRepository 중 좀 더 편하게 사용할 수 있는 RedisRepository 를 선택하였습니다.

그리고 refreshToken 을 생성할때 redis 에 저장하도록 하였습니다.

로그인 http request 를 보낸 뒤에 정상적으로 redis 에 저장이 되었는지 redis-cli 에서 확인해 볼까요?

(저도 아직은 Redis 에 대해 학습을 재대로 한 것이 아니라 어떤 구조로 저장이 되고 command 가 어떻게 되는지 알지 못합니다. 양해 부탁드려요!!)

 

위부터 순차적으로 명령어를 해석하자면

1. redis 에 저장된 type 이 무엇인지 알려줍니다. 현재 저는 set 으로 저장이 되고 있네요

2. redis 에 저장되어 있는 모든 key 들을 조회할 수 있습니다.

3. 찾고자 하는 key 가 redis 에 존재하는지 안하는지 알 수 있습니다. (1이면 존재한다는 뜻이고 0이면 없다는 뜻입니다)

 

redis-cli 에서 확인 했으니 실제로 spring boot 프로젝트에서 조회도 한번 해볼까요???

임시 api 를 생성해주었습니다.

 

 

정상적으로 console 창에 찍힌다면 원하는 대로 Redis 에 정상적으로 저장이 되었다는 뜻이겠죠???

http 요청을 한번 보내보겠습니다.

결과는????!!!

짠~~~(박수!!)

정상적으로 redis DB 에서 조회해온 것을 확인할 수 있습니다!!!!

 

마무리

맨날 해야지 해야지 생각만 하고 있다가 ㅋㅋㅋ 진짜로 구현해야하는 상황이 닥쳐서 이렇게 wsl 설정부터 redis 에 refreshToken 저장까지 한 과정을 써보았는데요 ㅎㅎ

처음해보는 거라 많이 힘들더라구요 ㅠㅠㅠ

 

그렇지만 여기서 끝이 아닙니다. 추후에는 AWS 를 사용해서 배포까지 하는게 목표인데 배포를 하게 된다면 host 설정도 변경해야 하고 만약 동일한 요청에 대해서 매번 Redis DB 에서 조회하는 것도 부하가 발생한다면 cache 를 사용하는 것도 고려해봐야 되고 여러가지 상황에 대해서 생각하고 결정해야 하는 것들이 발생할 것 같습니다.

 

사실 refreshToken 이라는 걸 사용하여 서버에게 책임을 부여하는 순간부터 stateless 한 구조를 포기하는 것이므로 좋은 설계냐? 라고 물어보신다면 솔직히 딱 잘라 대답은 못할 것 같습니다.

그러나 적어도 accessToken 을 갱신해야 하는 목적을 생각하고 우선순위가 더 높다고 생각된다면 본인만의 답으로 코딩하는 것이 제일 좋은 태도라고 생각합니다.

 

꽤 긴 글이었지만 끝까지 봐주신 여러분들께 감사함을 표하고 다들 무탈히 원하시는 작업들을 수행하길 바라겠습니다.