본문 바로가기
백엔드/스프링

[Spring] Redis 개념 및 활용법 with Spring Boot

by AI읽어주는남자 2025. 10. 21.
반응형

Redis with Spring Boot 복습 자료

이 문서는 제공된 Java 코드와 학습 노트를 바탕으로 Redis의 기본 개념과 Spring Boot에서의 활용법을 정리한 복습 자료입니다.

1. Redis 기본 개념

1.1. Redis란?

  • In-Memory Data Store: 데이터를 주기억장치(RAM)에 저장하여 매우 빠른 읽기/쓰기 속도를 제공하는 키-값(Key-Value) 구조의 저장소입니다.
  • NoSQL: 관계형 데이터베이스(RDB)와 달리 정해진 스키마가 없는 NoSQL의 한 종류입니다.
  • 주요 목적: 데이터베이스의 부하를 줄이기 위한 캐싱(Caching), 실시간 순위표, 세션 관리 등 빠른 응답이 요구되는 다양한 시나리오에 사용됩니다.

1.2. 데이터 저장 방식 비교

저장소 특징 주요 용도
데이터베이스 (MySQL 등) 영구 저장(HDD/SSD), 대용량 데이터, 트랜잭션 지원 핵심 데이터 영구 보관
HTTP 세션 서버 메모리에 저장, 서버 과부하 우려, 보안성 높음 로그인 상태 유지
Redis 임시 저장(RAM), 매우 빠름, TTL(유효기간) 설정 가능 DB 조회 결과 캐싱, 인증 토큰, 실시간 데이터

2. Spring Boot 연동 설정

2.1. 의존성 추가 (build.gradle)

Spring Boot에서 Redis를 사용하려면 spring-boot-starter-data-redis 의존성을 추가해야 합니다.

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

2.2. 연결 정보 설정 (application.properties)

Redis 서버의 호스트와 포트 정보를 설정합니다. (기본값: localhost:6379)

spring.data.redis.host=localhost
spring.data.redis.port=6379

2.3. RedisTemplate 빈 설정 (RedisConfig.java)

Spring에서 Redis에 데이터를 저장하고 조회하기 위해 RedisTemplate을 사용합니다. 이때, Java 객체를 Redis에 저장하려면 직렬화(Serialization) 과정이 필요합니다.

  • 직렬화(Serialization): Java 객체를 Redis에 저장 가능한 데이터 형식(예: JSON)으로 변환하는 과정.
  • 역직렬화(Deserialization): Redis에서 읽어온 데이터를 다시 Java 객체로 복원하는 과정.

RedisConfig.java는 이 RedisTemplate을 생성하고 직렬화 방식을 설정하는 역할을 합니다.

package example.day17;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        // Key는 String 타입으로 직렬화
        template.setKeySerializer(new StringRedisSerializer());
        // Value는 JSON/DTO 타입으로 직렬화 (Jackson 라이브러리 사용)
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        return template;
    }
}

3. RedisTemplate 핵심 사용법

RedisController.java를 통해 주요 사용법을 알아봅니다.

3.1. 데이터 저장 (SET)

  • opsForValue().set(key, value): 키-값 쌍을 저장합니다. 동일한 키에 다시 저장하면 덮어씁니다.
// 예시: 간단한 문자열 저장
redisTemplate.opsForValue().set("유재석", "90");
redisTemplate.opsForValue().set("강호동", "80");

3.2. 데이터 조회 (GET)

  • opsForValue().get(key): 특정 키에 해당하는 값을 조회합니다.
  • keys("패턴"): 특정 패턴에 맞는 모든 키를 Set 형태로 반환합니다. (*는 모든 키를 의미)
// 예시: "강호동" 키의 값 조회
Object value = redisTemplate.opsForValue().get("강호동"); // "80"

// 예시: 모든 키 조회
Set<String> keys = redisTemplate.keys("*");

3.3. 데이터 삭제 (DELETE)

  • delete(key): 특정 키와 값을 삭제합니다.
// 예시: "유재석" 키 삭제
redisTemplate.delete("유재석");

3.4. 유효 기간 설정 (TTL - Time To Live)

  • opsForValue().set(key, value, Duration): 데이터를 저장할 때 유효 기간을 설정합니다. 기간이 만료되면 데이터는 자동으로 삭제됩니다.
import java.time.Duration;

// 10초 동안만 유효한 인증번호 저장
String key = "auth:01012341234";
String code = "123456";
redisTemplate.opsForValue().set(key, code, Duration.ofSeconds(10));

4. 실용 예제: CRUD 및 인증 기능

4.1. DTO 객체 CRUD

Redis를 데이터베이스처럼 사용하여 StudentDto 객체를 저장, 조회, 수정, 삭제하는 예제입니다.

  • Key 전략: 중복을 피하기 위해 "student:{학번}"과 같은 패턴으로 키를 생성합니다.

StudentDto.java

package example.day17;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data @Builder
public class StudentDto{
    private int sno;
    private String name;
    private int kor;
    private int math;
}

RedisController.java (CRUD 부분)

// 1. 등록 (Create)
@PostMapping("")
public ResponseEntity<?> save(@RequestBody StudentDto studentDto){
    String key = "student:" + studentDto.getSno();
    studentTemplate.opsForValue().set(key, studentDto);
    return ResponseEntity.ok().body("[저장성공]");
}

// 2. 전체 조회 (Read All)
@GetMapping("")
public ResponseEntity<?> findAll() {
    Set<String> keys = studentTemplate.keys("student:*");
    List<Object> result = new ArrayList<>();
    for (String key : keys) {
        result.add(studentTemplate.opsForValue().get(key));
    }
    return ResponseEntity.ok().body(result);
}

// 3. 개별 조회 (Read One)
@GetMapping("/find")
public ResponseEntity<?> find(@RequestParam int sno) {
    String key = "student:" + sno;
    Object result = studentTemplate.opsForValue().get(key);
    return ResponseEntity.ok(result);
}

// 4. 수정 (Update)
@PutMapping("")
public ResponseEntity<?> update(@RequestBody StudentDto studentDto){
    String key = "student:" + studentDto.getSno();
    studentTemplate.opsForValue().set(key, studentDto); // 덮어쓰기 방식
    return ResponseEntity.ok(true);
}

// 5. 삭제 (Delete)
@DeleteMapping("")
public ResponseEntity<?> delete(@RequestParam int sno) {
    String key = "student:" + sno;
    boolean result = studentTemplate.delete(key);
    return ResponseEntity.ok(result);
}

4.2. 휴대폰 인증 번호 (TTL 활용)

TTL은 인증 번호처럼 일정 시간 동안만 유효해야 하는 데이터를 다룰 때 매우 유용합니다.

  1. 인증번호 발급: 사용자의 전화번호를 키로 하여 랜덤 인증번호를 생성하고, 짧은 유효 기간(예: 10초)을 설정하여 Redis에 저장합니다.
  2. 인증번호 확인: 사용자가 인증번호를 입력하면, Redis에서 해당 전화번호 키로 값을 조회하여 일치하는지 확인합니다.
    • 조회된 값이 없으면 "인증 시간 만료"를 의미합니다.
    • 값이 일치하면 인증 성공 처리 후, 즉시 해당 키를 Redis에서 삭제하여 재사용을 방지합니다.

RedisController.java (인증 부분)

// 인증번호 발급
@GetMapping("/auth/send")
public ResponseEntity<?> authSend(@RequestParam String phone){
    String key = "auth:" + phone;
    String code = String.format("%06d", new Random().nextInt(999999));
    // 10초 유효기간 설정
    redisTemplate.opsForValue().set(key, code, Duration.ofSeconds(10));
    return ResponseEntity.ok().body("인증코드 발급 완료 : " + code);
}

// 인증번호 확인
@GetMapping("/auth/confirm")
public ResponseEntity<?> authConfirm(@RequestParam String phone, @RequestParam String code) {
    String key = "auth:" + phone;
    Object savedCode = redisTemplate.opsForValue().get(key);

    if (savedCode == null) {
        return ResponseEntity.ok("인증실패 : 인증 만료 또는 코드 불일치");
    } else if (savedCode.equals(code)) {
        redisTemplate.delete(key); // 성공 시 인증코드 삭제
        return ResponseEntity.ok("인증성공");
    } else {
        return ResponseEntity.ok().body("인증실패");
    }
}
반응형