Redis 적용

박세건·2025년 2월 24일
0

기술 실습

목록 보기
18/18

✅ 0. 도커 및 Redis 설치

1. Docker Desktop 설치

  • 공식 사이트에서 Docker Desktop을 다운로드 후 설치합니다.

2. Redis 이미지 다운로드

docker pull redis

3. Docker 컨테이너 실행

docker run -d -p 6379:6379 --name docker_redis redis
  • 실행 상태 확인
docker ps

4. Redis CLI 접속

docker exec -it docker_redis redis-cli

✅ 1. Spring Boot에서 Redis 설정

1.1 build.gradle에 의존성 추가

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

1.2 application.yml에 Redis 설정

spring:
  data:
    redis:
      host: localhost
      port: 6379

1.3 Redis Client 선택

  • JedisLettuce 중 일반적으로 Lettuce를 사용합니다.

✅ 2. Redis 사용 방식

2.1 RedisRepository 사용 (간단한 CRUD)

public interface ShortUrlRedisRepository extends CrudRepository<ShortUrlResponseDto, String> {
}

2.2 RedisTemplate 사용 (더 많이 사용됨, 유연성 높음)

@Component
public class RedisTemplateTest {
    private final RedisTemplate<String,String> redisTemplate;

    @Autowired
    public RedisTemplateTest(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void test() {
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        valueOperations.set("Redis에 저장할 키","키값에 저장시킬 값");
    }
}

✅ 3. RedisConfig 추가

@Configuration
public class RedisCacheConfig implements CacheConfig {

    @Value("${spring.data.redis.host}")
    private String host;

    @Value("${spring.data.redis.port}")
    private int port;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(host, port);
    }

    @Bean
    public RedisTemplate<?,?> redisTemplate() {
        RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }
}

✅ 4. Controller, Service, DTO 구성

4.1 Controller

@RestController
@RequestMapping("/short-url")
public class ShortUrlController {

    private final ShortUrlService shortUrlService;

    @Autowired
    public ShortUrlController(ShortUrlService shortUrlService) {
        this.shortUrlService = shortUrlService;
    }

    @PostMapping("/generate")
    public ShortUrlResponseDto generateShortUrl(@RequestBody ShortUrlResponseDto shortUrlResponseDto) {
        return shortUrlService.generateShortUrl(shortUrlResponseDto);
    }

    @GetMapping("/get")
    public ShortUrlResponseDto getShortUrl(@RequestParam String originalUrl) {
        return shortUrlService.getShortUrl(originalUrl);
    }
}

4.2 DTO

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@RedisHash(value = "shortUrl", timeToLive = 60)
public class ShortUrlResponseDto implements Serializable {
    private static final long serialVersionUID = -1L;

    @Id
    private String originalUrl;
    private String shortUrl;
}

4.3 Service

public interface ShortUrlService {
    ShortUrlResponseDto generateShortUrl(ShortUrlResponseDto shortUrlResponseDto);
    ShortUrlResponseDto getShortUrl(String originalUrl);
}

4.4 ServiceImpl

@Service
public class ShortUrlServiceImpl implements ShortUrlService {

    private final ShortUrlRedisRepository shortUrlRedisRepository;

    @Autowired
    public ShortUrlServiceImpl(ShortUrlRedisRepository shortUrlRedisRepository) {
        this.shortUrlRedisRepository = shortUrlRedisRepository;
    }

    @Override
    public ShortUrlResponseDto generateShortUrl(ShortUrlResponseDto shortUrlResponseDto) {
        shortUrlRedisRepository.save(shortUrlResponseDto);
        return shortUrlResponseDto;
    }

    @Override
    public ShortUrlResponseDto getShortUrl(String originalUrl) {
        return shortUrlRedisRepository.findById(originalUrl)
                .orElse(new ShortUrlResponseDto("캐시를 사용하지 않고 생성된 객체", "캐시를 사용하지 않고 생성된 객체"));
    }
}

만약 RedisTemplate 사용한다면..

Interface:

public interface ShortUrlServiceByRedisTemplate {
    ShortUrlResponseDto generateShortUrl(ShortUrlResponseDto shortUrlResponseDto);
    ShortUrlResponseDto getShortUrl(String originalUrl);
}

Implementation:

@Service
public class ShortUrlServiceByRedisTemplateImpl implements ShortUrlServiceByRedisTemplate {
    private final RedisTemplate<String, ShortUrlResponseDto> redisTemplate;
    @Autowired
    public ShortUrlServiceByRedisTemplateImpl(RedisTemplate<String, ShortUrlResponseDto> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    @Override
    public ShortUrlResponseDto generateShortUrl(ShortUrlResponseDto dto) {
        // ✅ Redis에 직접 데이터 저장 (Key: originalUrl, Value: ShortUrlResponseDto)
        redisTemplate.opsForValue().set(dto.getOriginalUrl(), dto);
        return dto;
    }
    @Override
    public ShortUrlResponseDto getShortUrl(String originalUrl) {
        // ✅ Redis에서 데이터 조회
        ShortUrlResponseDto result = redisTemplate.opsForValue().get(originalUrl);![](https://velog.velcdn.com/images/parksegun/post/f4823f36-7e9e-497f-b185-c3aa4af465fa/image.jpg)
![](https://velog.velcdn.com/images/parksegun/post/dd26b116-6837-4cb1-af32-9421cfd4fc3f/image.jpg)
    if (result != null) {
        System.out.println("✅ Redis에서 데이터 조회 성공: " + result.getShortUrl());
        return result;
    } else {
        System.out.println("❌ Redis에 데이터가 없습니다. DB에서 조회하거나 캐싱 필요");
        return new ShortUrlResponseDto("캐시를 사용하지 않고 생성된 객체", "캐시를 사용하지 않고 생성된 객체");
    }
}

}


---

## ✅ 5. Swagger 추가 및 설정

### 5.1 build.gradle에 의존성 추가
```gradle
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'

5.2 application.yml에 설정

springdoc:
  swagger-ui:
    path: /swagger-ui.html
  api-docs:
    path: /v3/api-docs

✅ 6. Redis 명령어 정리

명령어설명
SET key value문자열 데이터를 저장
GET key문자열 데이터를 조회
DEL key특정 키를 삭제
HSET key field value해시(Hash)에 필드와 값을 저장
HGET key field해시(Hash)의 특정 필드를 조회
HGETALL key해시(Hash)의 모든 필드와 값을 조회
LPUSH key value리스트(List)의 왼쪽에 값 추가
RPUSH key value리스트(List)의 오른쪽에 값 추가
LPOP key리스트(List)의 왼쪽에서 값 제거 및 반환
RPOP key리스트(List)의 오른쪽에서 값 제거 및 반환
SADD key value셋(Set)에 값 추가 (중복 불가)
SMEMBERS key셋(Set)의 모든 요소 조회
ZADD key score memberSorted Set에 점수와 요소 추가
ZRANGE key start stopSorted Set의 범위 조회
ZRANK key memberSorted Set에서 특정 요소의 순위 조회
EXPIRE key seconds특정 키의 TTL 설정
KEYS *모든 키 조회

✅ 7. 결과 확인

  1. Swagger로 POST /short-url/generate 호출 시:
  • Redis에 데이터가 저장됨
  • CLI에서 HGETALL shortUrl:example.com 명령어로 확인 가능
  1. Swagger로 GET /short-url/get 호출 시:
  • Redis에서 데이터 조회
  1. TTL 60초 설정을 통해 60초 후 데이터 자동 삭제 확인

✅ 8. 성능 테스트 결과

  • Redis를 사용했을 때 약 5배 빠른 응답 속도 확인 (7ms)

💡 추가 학습 포인트

  • Redis에서 HGETALL 명령어의 결과는 짝수 개의 요소로 반환되며, 홀수 번째 요소는 필드 이름입니다.
  • _class 필드는 Spring Data Redis가 직렬화 시 자동으로 추가하는 클래스 정보입니다.

🚀 결론

  • RedisTemplate은 더 많은 기능과 유연성을 제공하므로 대규모 프로젝트에서 더 많이 사용됩니다.
  • RedisRepository는 간단한 CRUD에 적합합니다.
  • TTL 설정을 통해 캐싱 기능으로도 효과적으로 사용 가능합니다.
profile
멋있는 사람 - 일단 하자

0개의 댓글