문제: 장소의 조회수를 어떻게 설계해야 할지 확인해 보려고 한다. 원래 CRUD를 가지고 조회수를 증가시키려면, POST를 이용하여 +1씩 증가시켰다. 그런데 인기 있는 장소라면 많은 사람들이, 동시에 요청을 할 수 있다.
만약 1000명의 사람이 요청을 하면 어떨까?
DB 반영이 느릴 수 있다. DB에 조회수를 반영시킬 때 다음과 같은 과정을 거친다.
DB connection get → 해당 테이블 조회 → 현재 조회수 읽기 → 값 증가(SQL문 실행) → commit → connection return
이 작업을 1000번 계속 동작해야 한다.
→ Redis는 자주 접근하는 데이터를 캐싱하여 접근 시간을 개선한다.

그럼 인기 있는 장소일 때, 여러 명의 사람이 동시에 요청을 하면 어떤 문제점이 생길까?
동시성의 문제가 발생한다.
Lost Update Problem이 발생한다. 업데이트 누락 문제는 다음과 같다. T1(트랜잭션)이 항목을 업데이트 했을 때, T2도 같은 것을 업데이트 하면서 T1의 업데이트 내용을 덮어써서 손실되는 현상을 말한다.
이 문제를 해결하기 위해서는 아래 3가지 해결방법이 있다.
본 프로젝트에서는 Redis를 사용하여 조회수 성능을 높여 보려고 한다.
가장 중요한 점은 동시성 문제를 해결하는 것은 동시성 문제를 해결하여 정확성을 높이기 위한 부분이고, Redis를 사용하는 것은 성능을 높이기 위함이다.
성능 측면에서, Redis에는 INCR key가 있다. (INCR key는 원자적(atomic)으로 처리된다.)
INCR은 key에 저장된 숫자에 1을 증가시키는 것이다. 여러 요청이 동시에 와도 1씩 안전하게 증가시킨다. 조회수를 증가시키는 것에 매우 잘 활용할 수 있다. (atomic으로 처리하기 때문에 lock을 걸 필요도 없다. 즉, 동시성 문제에 대한 해결방안이기도 하다.)
또한 Redis는 시간복잡도가 O(1)인만큼 매우 빠른 속도를 가지고 있다. 조회수를 처리할 때 바로 바로 처리할 수 있는, 시스템에 부담을 DB보다 비교적 덜 주는 Redis를 활용하는 것이 맞다고 판단하였다.
Redis를 활용하여 조회수 증가를 시키고 일정한 시간이 되면 → DB에 해당 값을 반영시킨다.
Redis는 (key, value)를 가진다. → key는 CRUD 하는 작업에 쓰인다.
opsForValue() : Redis String 타입을 읽고 쓰기 위한 Redis 메서드 중 하나이다.
Redis 이용한 코드 변경
Place 번호(id)를 통해 Redis에 저장된 조회수(생성한 Redis Key를 활용하여)를 가지고 오는 로직
String key = generateViewKey(id);
String redisValue = redisTemplate.opsForValue().get(key);
Place 번호(id)의 조회수를 올려주는 로직 → 마찬가지로 생성한 Redis Key를 활용하여 id 조회수를 올려준다.
String key = generateViewKey(id);
redisTemplate.opsForValue().increment(key);
Redis 반영후 결과

→ 그러면 Redis로 조회수가 잘 올라갔는지 어떻게 확인할까?
