일일 조회수, 일일 무료 베스트, 일일 유료 베스트 별 소설 노출 기능 구현을 위해 작성한 글이다.

‘일일’이라는 것은 하루 동안의 많이 읽힌 소설을 노출시키는 것이다. 그렇다는 것은 정보가 실시간으로 업데이트 되어야 하며, DB에서 직접 통계를 내어 데이터를 가져오는 것은 대용량 트래픽 환경에서 DB에 부하를 줄 수 있다.

처음에는 단순하게 데이터베이스에서 조회수 순으로 나열하면 되겠다 라고 생각을 했지만, 대용량 트래픽 환경이라는 배경을 생각하니, 이 조차도 단순히 데이터베이스에 조회하게 되면 장애가 생길 가능성이 있다는 생각이 들었다.

게다가 메인 화면은 사용자들이 가장 많이 요청하는 화면이기 때문에, 메인 화면에서는 DB로 쿼리문이 날아가면 안된다는 생각이 들었다.

그리고 부하 테스트를 통해 많은 데이터를 가져와야 했을 때 성능을 개선한 경험이다.

랭킹 집계


가장 먼저 나의 웹 소설 서비스는 랭킹을 조회하기 위해 소설 안에 있는 에피소드들의 조회수를 총 합한 값을 내림차순으로 계산하여 랭킹을 정한다.

테스트 환경에서는 10000개의 소설이 등록되어있고, 각 소설 당 15개의 에피소드들이 등록되어 있다. 총 약 150,000 개의 데이터들을 준비해두었다. 그리고 다음과 같은 쿼리를 랭킹 조회 시 마다 데이터베이스 서버로 날렸다.

SELECT novel0_.novel_id    AS col_0_0_,
       novel0_.title       AS col_1_0_,
       novel0_.author      AS col_2_0_,
       novel0_.description AS col_3_0_,
       novel0_.genre       AS col_4_0_,
       Sum(episodes1_.hit) AS col_5_0_
FROM   novel novel0_
       LEFT OUTER JOIN novel_episode episodes1_
                    ON novel0_.novel_id = episodes1_.novel_id
GROUP  BY novel0_.novel_id

소설(novel) 조회 시에 소설 에피소드(novel_episode)을 조인하여 데이터를 가져온다. 즉 랭킹 갱신 시에 10만개가 넘는 데이터를 조회하게 되는 것이다.

그리고 성능을 측정해봤을 때, 다음과 같은 결과가 나왔다.

직접 조회 시 걸리는 시간

직접 조회 시 걸리는 시간

0.7초가 걸렸다. 1초도 안되는 시간이지만, 대용량 트래픽 환경에서는 0.7초라는 서버에 꽤나 크리티컬한 시간이라고 생각했다. 이유는 매번 랭킹 조회 시에 대량의 데이터를 조회하기 때문에 시간이 꽤나 오래걸리는 것이다.

그래서 이를 캐싱으로 개선해보겠다.

캐싱으로 성능 개선하기 (Redis)