240218 TIL | Redis 사용

2024. 2. 18. 13:42· 왕초보일지
목차
  1. Redis 설정
  2. 1 설치
  3. 2 dependencies
  4. 3 인텔리제이 데이터베이스 연결
  5. 4 application.yml 설정 (로컬)
  6. 5 RedisConfig 
  7. 코드
  8. Controller
  9. Service

인텔리제이에서 스프링 부트와 Redis 를 연결하고

Sorted set 자료구조를 이용해 인기 검색어 순위를 저장하고 조회하는  테스트를 해봤다.


spring boot kotlin 

redisTemplate

Redis 설정

 

1 설치

redis 설치가이드

 

2 dependencies

implementation ("org.springframework.boot:spring-boot-starter-data-redis:2.3.1.RELEASE")

 

3 인텔리제이 데이터베이스 연결

 

4 application.yml 설정 (로컬)

spring:
  data:
   redis:
     port: 6379 // 기본 포트
     host: localhost

 

5 RedisConfig 

package com.sparta.bubbleclub.global.config

import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.serializer.StringRedisSerializer

@Configuration
class RedisConfig {
    @Value("\${spring.data.redis.port}")
    private val port = 0

    @Value("\${spring.data.redis.host}")
    private val host: String = ""

    @Bean
    fun redisConnectionFactory(): RedisConnectionFactory {
        return LettuceConnectionFactory(host, port)
    }


    @Bean
    fun redisTemplate(): RedisTemplate<String, String> {
        val redisTemplate: RedisTemplate<String, String> = RedisTemplate()
        redisTemplate.keySerializer = StringRedisSerializer() //key 깨짐 방지
        redisTemplate.valueSerializer = StringRedisSerializer() //value 깨짐 방지
        redisTemplate.connectionFactory = redisConnectionFactory()
        return redisTemplate
    }


}

 

 

 

코드

Controller

package com.sparta.bubbleclub.domain.keyword.controller

import com.sparta.bubbleclub.domain.bubble.dto.request.SearchKeywordRequest
import com.sparta.bubbleclub.domain.bubble.dto.response.BubbleResponse
import com.sparta.bubbleclub.domain.keyword.dto.response.KeywordResponse
import com.sparta.bubbleclub.domain.keyword.service.KeywordService
import jakarta.validation.Valid
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Slice
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("api/v1/keywords")
class KeywordController(
    private val keywordService: KeywordService
) {

  ...
    // 키워드로 검색
    @GetMapping("/search")
    fun searchByKeyword(
        @Valid request: SearchKeywordRequest
    ): ResponseEntity<String> {
        keywordService.setKeywordScore(request.keyword)
        return ResponseEntity.ok().body("")

    }

    // 인기 검색어 조회
    @GetMapping("/ranks")
    fun searchKeywordRanking(): List<KeywordResponse> {
        return keywordService.searchKeywordRankingByRedis()
    }
}

 

 

Service

package com.sparta.bubbleclub.domain.keyword.service

import com.sparta.bubbleclub.domain.bubble.dto.request.SearchKeywordRequest
import com.sparta.bubbleclub.domain.keyword.dto.response.KeywordResponse
import com.sparta.bubbleclub.domain.keyword.repository.KeywordRepository
import jakarta.transaction.Transactional
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.stereotype.Service

@Service
class KeywordService(
    private val keywordRepository: KeywordRepository,
    private val redisTemplate: RedisTemplate<String, String>
) {
...
    private val zSetOperations = redisTemplate.opsForZSet()

    companion object {
        private const val REDIS_KEY = "keyword"
    }

    // keyword 저장
    @Transactional
    fun setKeywordScore(keyword: String): Boolean {

        // redis 에 keyword 있는지 검사, 없으면 추가
        zSetOperations.addIfAbsent(REDIS_KEY, keyword, 0.0)

        // increaseScore() 호출
        increaseScore(keyword)

        return true
    }

    // score ++
    private fun increaseScore(keyword: String) {
        zSetOperations.incrementScore("keyword", keyword, 1.0)
    }

    // 인기 검색어 조회
    fun searchKeywordRankingByRedis(): List<KeywordResponse> {
        val rank =zSetOperations.reverseRange("keyword", 0, 9) ?: emptySet()
        return rank.map { KeywordResponse(keyword = it) }
    }


}

 

 

구조

특정 검색어 $keyword 로 데이터 조회 api

-> 검색어 $keyword 가 "keyword" 라는 key 에 value 로 있는지 확인, 없으면 추가

-> "keyword" key 에 $keyword value 의 score 값을  1씩 더함

검색어 순위 조회 api

-> "keyword" key의 높은 것부터 낮은 것 순으로 0번째부터 9번째까지 10개의 데이터를 가져와서 반환함

 

 

결과

키워드로 검색을 할 때마다 각각의 score가 1씩 올라가고

순위를 조회하면 score 가 높은 것부터 차례대로 반환된다.

 

 

어떻게 흘러가나 궁금해서 저장할 때랑 조회할 때 찍고 안에 들어가봤는데 뭐가 뭔지 하나도 모르겠다 

안에 까보면서 즐거움 느끼는 사람들 대단....

 

 

 

해야할 것

redis 를 사용할 때 명령어가 어떻게 날아가는지 확인

데이터가 영구적으로 저장되므로 삭제시켜주어야한다 -> 만료시간 설정

redis cache 사용 -> 유효시간 설정 -> 삭제된 후에 기존의 순위는 어떻게 나타내지??

 

 

 

 

 

Redis Method doc

'왕초보일지' 카테고리의 다른 글

240220 TIL | 더미 데이터 집어넣기  (1) 2024.02.20
240219 TIL |  (0) 2024.02.19
240216 TIL |  (1) 2024.02.16
240215 TIL |  (1) 2024.02.15
240214 TIL |  (2) 2024.02.14
  1. Redis 설정
  2. 1 설치
  3. 2 dependencies
  4. 3 인텔리제이 데이터베이스 연결
  5. 4 application.yml 설정 (로컬)
  6. 5 RedisConfig 
  7. 코드
  8. Controller
  9. Service
'왕초보일지' 카테고리의 다른 글
  • 240220 TIL | 더미 데이터 집어넣기
  • 240219 TIL |
  • 240216 TIL |
  • 240215 TIL |
다시은
다시은
🔥
다시은
재은로그
다시은
전체
오늘
어제
  • 분류 전체보기 (127)
    • 코딩테스트 (40)
    • Language (2)
      • JAVA (2)
      • Kotlin (0)
      • TypeScript (0)
    • SQL (1)
    • 인프라 (1)
    • 왕초보일지 (77)
    • 회고 (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • SQL문법
  • Kotlin
  • 문자열변환
  • 스프레드시트
  • googleapis
  • sql
  • mysql

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
다시은
240218 TIL | Redis 사용
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.