일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 백준#BOJ#12865#평범한배낭
- 백준#BOJ#2615#오목
- 백준#boj#16932#모양만들기
- 백준#boj#12755
- 백준#BOJ#1939#중량제한
- 백준#BOJ#8012#한동이는영업사원
- 백준#BOJ#14501#퇴사#브루트포스
- Today
- Total
순간을 성실히, 화려함보단 꾸준함을
wsl+docker 를 사용한 spring boot + Redis 사용하기!! 본문
안녕하세요
벌써 글또 프로그램이 마지막을 향해서 달려가고 있습니다.
앞으로 총 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
위의 링크에 들어가서 패키지를 설치해 준 뒤 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 를 설치해봐야겠죠??
위 링크에 들어가 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 를 참고해주시면 될 것 같습니다. (굉장히 친절하게 잘 알려주고 있습니다)
이제 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 를 사용하는 방법은 공식문서가 굉장히 상세히 잘 나와있더라구요.
그래서 저는 공식문서로만으로도 구현하는데 큰 문제가 없었습니다.
먼저 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 을 갱신해야 하는 목적을 생각하고 우선순위가 더 높다고 생각된다면 본인만의 답으로 코딩하는 것이 제일 좋은 태도라고 생각합니다.
꽤 긴 글이었지만 끝까지 봐주신 여러분들께 감사함을 표하고 다들 무탈히 원하시는 작업들을 수행하길 바라겠습니다.
'나의 개발 메모장' 카테고리의 다른 글
인텔리제이 .http 파일로 MultipartFile 전송해보기 (0) | 2023.08.19 |
---|---|
글또 8기를 마치며 (4) | 2023.07.16 |
Http method 에 따라 동일한 URI 를 다르게 처리하는 방법 (0) | 2023.06.03 |
어느 날 이넘(enum) 이 내게 찾아왔다! (0) | 2023.05.17 |
jvm 시스템 파라미터를 사용하여 배포환경에 따른 active 구분 (0) | 2023.05.06 |