JSCODE Logo
JSCODE 박재성JSCODE 제이온JSCODE 시니
과외유튜브블로그후기
완강 후기 이벤트블로그 리뷰 이벤트AWS SAA 합격 후기 이벤트
회사명 : JSCODE대표 : 박재성사업자 등록번호 : 244-22-01557통신판매업 : 제 2023-인천미추홀-0381 호

서울특별시 구로구 경인로 20가길 11(오류동, 아델리아)

Copyright ⓒ 2026 JSCODE - 최상위 현업 개발자들의 프로그래밍 교육 All rights reserved.

이용약관개인정보처리방침

비전공자도 이해할 수 있는 Redis 중급/실전

Redis로 ‘쓰기 작업’에 대한 DB 부하 줄이기

Redis의 수많은 자료 구조를 효율적으로 배우려면?
List 자료 구조 (RPUSH, LRANGE, LPOP 등)
[실습] 좋아요 수 폭증으로 인한 DB 부하를 Redis로 해결하기 - 1
[실습] 좋아요 수 폭증으로 인한 DB 부하를 Redis로 해결하기 - 2

Redis로 동시성 이슈 해결하기

String 자료 구조 (SET, GET, DEL, SETNX)
[실습] 재고를 차감할 때 동시성 이슈로 인한 오차가 발생하지 않도록 만들기 - 1
[실습] 재고를 차감할 때 동시성 이슈로 인한 오차가 발생하지 않도록 만들기 - 2
[실습] 재고를 차감할 때 동시성 이슈로 인한 오차가 발생하지 않도록 만들기 - 3

Redis로 인기 검색어 구현하기

Sorted Set 자료 구조 (ZADD, ZRANGE, ZINCRBY)
[실습] 많이 검색한 키워드 Top 10을 보여주는 '인기 검색어 기능’ 만들기 - 1
[실습] 많이 검색한 키워드 Top 10을 보여주는 '인기 검색어 기능’ 만들기 - 2

Redis로 API 요청 횟수 제한 기능 구현하기 (Rate Limiting)

Sorted Set 자료 구조 (ZCARD, ZREMRANGEBYSCORE, EXPIRE)
[실습] 악의적인 요청을 방지하기 위해, 10초당 API 요청 횟수를 5회로 제한하기 - 1
[실습] 악의적인 요청을 방지하기 위해, 10초당 API 요청 횟수를 5회로 제한하기 - 2

Redis를 활용해 내 위치를 기준으로 반경 1km에 위치한 카페 찾기

Geospatial 자료 구조 (GEOADD, GEOPOS, GEODIST, GEOSEARCH)
[실습] 내 위치를 기준으로 반경 1km에 위치한 카페 찾기 - 1
[실습] 내 위치를 기준으로 반경 1km에 위치한 카페 찾기 - 2

Redis로 하루 동안 서비스에 방문한 사용자 수(DAU) 카운팅하기

Set 자료 구조 (SADD, SMEMBERS, SCARD)
Bitmap 자료 구조 (SETBIT, GETBIT, BITCOUNT)
Set과 Bitmap의 공통점 / 차이점
[실습] 하루 동안 서비스에 방문한 사용자 수(DAU) 카운팅하기 - 1
[실습] 하루 동안 서비스에 방문한 사용자 수(DAU) 카운팅하기 - 2
[실습] 하루 동안 서비스에 방문한 사용자 수(DAU) 카운팅하기 - 3

Redis를 세션 스토리지로 활용하기

Hash 자료 구조 (HSET, HGET, HGETALL)
서버가 2대 이상일 경우, Redis로 세션 스토리지를 구축해야 하는 이유
[실습] 인증 기능을 로컬 세션 스토리지로 구현했을 때 발생하는 문제점 - 1
[실습] 인증 기능을 로컬 세션 스토리지로 구현했을 때 발생하는 문제점 - 2
[실습] Redis로 세션 스토리지 구축하기
← 블로그 목록으로 돌아가기

[실습] 많이 검색한 키워드 Top 10을 보여주는 '인기 검색어 기능’ 만들기 - 2

JSCODE 박재성
JSCODE 박재성
2026. 02. 25.
author
JSCODE 박재성
category
Redis
createdAt
Jan 12, 2026 12:08 AM
isPublic
isPublic
series
비전공자도 이해할 수 있는 Redis 중급/실전
slug
build-popular-search-keywords-feature-part-2
type
post
updatedAt
Feb 25, 2026 09:00
👨🏻‍🏫
이번에는 검색 API와 인기 검색어 조회 API를 Redis를 활용해 구현해보자.

✅ 구현 방법

notion image
  • 인기 검색어 조회 API에서는 인기순으로 검색어를 정렬해야 하기 때문에, 자동 정렬을 해주는 자료구조인 Sorted Set을 활용한다.
  • 검색을 할 때마다 score를 1 증가시킴으로써 인기 검색어를 구분한다.
 
 

✅ 실습

  1. 코드 작성하기
    1. SearchService
      @Service @RequiredArgsConstructor public class SearchService { private final SearchRepository searchRepository; private final RedisTemplate<String, String> redisTemplate; ... public void searchWithRedis(String keyword) { // Redis 명령어에서 'ZINCRBY search_keyword_ranking 1 [keyword]'와 동일 // ZINCRBY 명령어를 사용하여 해당 keyword의 score를 1 증가시킴 // (만약 해당 키워드가 존재하지 않으면 새로 추가하고 score를 1로 설정함) redisTemplate.opsForZSet() .incrementScore("search_keyword_ranking", keyword, 1.0); } public List<String> getTop10KeywordsWithRedis() { // Redis 명령어에서 'ZRANGE [key] [start index] [end index] REV'와 동일 // REV 옵션을 사용하여 Score가 높은 순(내림차순)으로 0~9번 인덱스 데이터를 조회 Set<String> topKeywords = redisTemplate.opsForZSet() .reverseRange("search_keyword_ranking", 0, 9); // Set을 List로 변환하여 반환 (null일 경우 빈 리스트 반환) return new ArrayList<>(topKeywords); } }
       
      SearchController
      @RestController @RequiredArgsConstructor @RequestMapping("/search") public class SearchController { private final SearchService searchService; ... @GetMapping("/redis") public void searchWithRedis(@RequestParam String keyword) { searchService.searchWithRedis(keyword); } @GetMapping("/top10/redis") public List<String> getTop10KeywordsWithRedis() { return searchService.getTop10KeywordsWithRedis(); } }
       
  1. 서버 실행시키기
    1. notion image
       
  1. 부하테스트 스크립트 살펴보기
    1. 이전에 실행시켰던 스크립트(script_3-1.js)와 코드가 대부분 똑같고, 새로 만든 API에 맞게 주소만 변경해주었다.
      scripts/script_3-2.js
      import http from 'k6/http'; import {check} from 'k6'; import {randomItem} from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; export const options = { // 가상 유저(VUs) 100명으로 설정 vus: 100, // 테스트를 10초 동안 진행 duration: '10s', }; // 검색어 리스트 정의 const keywords = [ 'spring', 'java', 'redis', 'mysql', 'jpa', 'k6', 'performance', 'test', 'load', 'stress', 'docker', 'kubernetes', 'aws', 'cloud', 'microservices', 'python', 'javascript', 'react', 'vue', 'angular' ]; export default function () { // 1. 검색 API 호출 // 랜덤한 키워드 선택 const keyword = randomItem(keywords); // 검색 요청 const searchRes = http.get(`http://localhost:8080/search/redis?keyword=${keyword}`); check(searchRes, { 'search status is 200': (r) => r.status === 200, }); // 2. 인기 검색어 조회 API 호출 const top10Res = http.get('http://localhost:8080/search/top10/redis'); check(top10Res, { 'top10 status is 200': (r) => r.status === 200, }); }
       
  1. 부하테스트 진행하기
    1. $ k6 run scripts/script_3-2.js
      notion image
      부하테스트를 해보니 검색 API와 인기 검색어 조회 API의 평균 TPS가 40422로 성능이 눈에 띄게 향상된 걸 확인할 수 있다.
 
  1. 인기 검색어 조회 API가 정말 잘 작동하는 지 테스트해보기
    1. notion image
 
 

✅ 정리

순위별 데이터를 조회해야 하는데 대용량 트래픽을 감당해야 하는 상황이라면, Redis의 Sorted Set을 활용하는 걸 고려해보자.
 
📎
이 글은 비전공자도 이해할 수 있는 Redis 중급/실전 강의의 수업 자료 중 일부입니다.