[Springboot] 스프링에 Redis 도입하기 개요

winluck·2023년 7월 20일
1

Springboot

목록 보기
2/18
post-thumbnail

요즘 백엔드는 Redis가 필수다. Redis가 효율적이다...
그런 이야기가 참 많이 들리는 요즘이다.

6월 말부터 Spring을 활용한 토이 서버 프로젝트를 프런트엔드 없이 혼자 끄적이다가 마무리했는데, 반성해야 할 점이 꽤 많고, 지금이 아니면 Redis나 Kafka 같은 기술을 시도해보기 어려울 것 같아, 프런트엔드 선배 한 명과 함께 Redis와 mySQL을 활용한 토이 프로젝트를 시작하게 되었다.

Redis를 쓰려면 당연히 Redis가 무엇인지는 기본적으로 알아야 한다.

근데 Redis가 뭐에요?

GPT에게 물어보았다.

"Redis는 오픈 소스 기반의 인메모리 데이터 저장소입니다. "Remote Dictionary Server"의 약자로, 특히 데이터베이스, 캐시, 메시지 브로커 등으로 사용되는 인기있는 데이터 구조 서버입니다. Redis는 Key-Value 형태로 데이터를 저장하며, 메모리에 데이터를 유지하므로 데이터에 빠르게 액세스할 수 있습니다.

Redis는 여러 가지 특징들로 인기를 얻었습니다:

  1. 인메모리 데이터 저장: Redis는 메모리에 데이터를 저장하기 때문에 매우 빠른 읽기/쓰기 속도를 제공합니다. 이는 데이터베이스나 캐시 시스템으로 사용할 때 매우 유용합니다.
  2. 다양한 데이터 구조 지원: Redis는 단순한 Key-Value 구조 뿐만 아니라 다양한 데이터 구조(문자열, 해시, 목록, 집합, 정렬된 집합 등)를 지원하여 데이터를 더 효율적으로 조직화할 수 있습니다.
  3. 지속성: Redis는 데이터를 디스크에 저장하고, 필요한 경우에만 디스크에서 데이터를 로드하여 데이터를 영구적으로 보존할 수 있습니다.
  4. 높은 가용성: Redis는 데이터 복제와 같은 메커니즘을 제공하여 장애 복구 및 고가용성을 지원합니다.
  5. Pub/Sub 메시징: Redis는 발행/구독 메시징 패턴을 지원하여 실시간 메시징 시스템을 구현하는 데 유용합니다.

Redis는 웹 응용 프로그램, 세션 관리, 게임, 캐싱, 실시간 분석 등 여러 분야에서 사용되고 있으며, 많은 개발자들이 Redis를 활용하여 확장 가능하고 빠른 데이터 처리를 구현합니다."

쉽게 말하면 메인 메모리 안에서 굴러가는 데이터 저장소라고 생각하면 된다.

우리는 보통 mySQL 등의 SQL 데이터베이스를 Disk에 두고 관리한다.

전공 수업 때 배웠듯이 이 경우 데이터에 대한 생성, 수정, 삭제 요청에 대응하기 위해서는 메모리에서 디스크로, 그리고 디스크에서 메모리로의 이동이 불가피하다. 이는 당연히 자원이 소모되는 일이며, 적은 수의 데이터라면 상관이 없겠지만, 다수의 사람들이 복잡한 형태나 조건을 수반하는 데이터를 실시간으로 조회 및 수정하는 경우 짧은 시간 안에 다양한 쿼리들이 처리되어야 하기에 부담이 커질 것이다.

Redis의 강점

Redis는 메인 메모리 안에서 데이터를 관리하기 때문에 빠른 읽기/쓰기 속도를 제공한다. 위 장점의 5번에서 드러나듯이, 실시간 메시징 시스템을 구현하는 데 유용하다는 언급이 있다.

내가 만들고자 하는 서버는 다음과 같은 특징을 갖는다.

  • 유저, 게시물, 댓글, 좋아요, 태그, 알림 테이블이 기본적으로 존재하고 일부 테이블은 중간 테이블을 형성하는 DB(mySQL)를 기반으로 한다.
  • 조회와 같은 기능은 Redis의 캐싱을 활용해 시간을 단축시키고자 한다.
  • 유저는 특정 태그를 "구독"하여, 특정 태그를 가진 게시물이 업로드되거나, 자신의 게시물을 누군가 좋아요를 누르면 알림을 수신한다. 즉 Redis의 Pub/Sub 기능을 활용하기 적합하다.

이제 왜 사용해야 하는지는 간단하게 알게 되었으니, 실제로 Springboot에 적용해보자.

Springboot에 Redis 도입

먼저 redis를 MacOS에 설치해야 한다.

$ brew install redis

설치가 끝났다면, springboot 프로젝트에 아래와 같은 의존성을 추가하자.

build.gradle

그리고 application.yaml에 다음과 같은 코드를 추가하자.

application.yaml

이제 기본적인 세팅이 이루어졌다.

RedisConfig.class

보통 RedisConfig는 ???application.class와 같은 경로에 존재한다.

물론 이런 식으로 import 처리하면 경로는 크게 문제가 되지 않는다.

User.class

기능 구현을 위해 사용될 가장 기본적인 domain에 해당하는 User 객체를 생성하였다.
@RedisHash(value = "?", timeToLive = ?)를 이용하여, Redis에 몇 초 동안 저장될지, 어떤 객체 타입인지를 Springboot에서 Redis에게 알려준다.

Redis는 JPA와 유사하게 Repository를 제공하지만 약간의 차이가 있다.
Redis에서 Repository는 트랜잭션 연산을 지원하지 않는다.

  • 트랜잭션 연산이란?
    여러 개의 연산을 하나의 논리적인 작업 단위로 묶어서 원자성, 일관성, 격리성, 지속성을 보장하는 것
  • 왜 필요한가?
    데이터베이스의 안정성, 일관성, 무결성을 보장하기 위해서!

Redis에서 트랜잭션 연산을 활용하려면 RedisTemplate를 활용해야 한다.
가벼운 예시이므로, RedisRepository를 활용하여 Redis에 휘발성 데이터를 삽입해보자!

UserRedisRepository.class

UserRedisTest

테스트 코드가 성공적으로 실행되면 Redis-cli에서 확인할 수 있다. 터미널을 켜고 Redis-cli를 입력한 뒤, 다음과 같은 명령어를 입력해보자.

  • keys *를 통해, 현재 활성화된 key를 확인할 수 있다. 우리가 user를 RedisHash에 추가해주었으므로, 크게 user라는 key 안에서, 잡다한 문자열이 붙어있는(@Id가 null이기 때문이다.) key가 바로 우리가 테스트 코드를 통해 만든 key이다.
  • type "key" 를 통해 이 key의 type을 알 수 있다.
  • ttl "key" 를 통해 이 key가 소멸될 때까지 남은 시간을 알 수 있다.
  • hgetall "key"를 통해 이 key의 value에 접근할 수 있다.

이로써 Redis에 대해 가볍게 알아보았다.

Redis는 캐싱을 앞세운 강력한 도구지만, ttl을 보면 알 수 있듯 휘발성이며, 데이터를 저장하여 보존해야 하는 데이터베이스 기존의 역할까지 안정적으로 소화하지는 못한다. 결국 데이터를 최종적으로 관리하는 mySQL과 같은 RDB는 여전히 필요하다. 그럼에도 불구하고 캐시가 메모리에서 뿜어내는 성능 향상 효과처럼, Redis 역시 이와 비슷한 파괴력으로 여러 실시간 서비스에서 활약하는 것이 아닐까 싶다.

이제부터 만들어갈 프로젝트에서 mySQL과 Redis, Springboot가 어떻게 조화를 이루어나가야할 지 많은 시행착오를 겪으며 작성해보겠다.

profile
Discover Tomorrow

2개의 댓글

comment-user-thumbnail
2023년 7월 20일

글 잘 봤습니다, 많은 도움이 되었습니다.

1개의 답글