240711 실전 프로젝트 - 대용량 프로젝트 해설과 KPT 회고

노재원·2024년 7월 11일
0

내일배움캠프

목록 보기
80/90

대용량 프로젝트 해설 세션

이번 프로젝트 자체가 대용량 데이터를 다루는 데에 어느정도 초점이 있어서 난이도도 대용량 데이터를 다루는 초점으로 나뉘어져 있었는데 그 중 나는 동시성 제어를 진행했을 뿐이다.

세션은 난이도별로 전부 다뤄주셔서 핵심 키워드를 기록해봤다.

대용량 데이터 제어

몇십만 건의 데이터가 있는 CSV 파일을 읽는 제어 과제가 있었다.

보통 PK로 만들어지는 기본 Index만 사용하지만 created_at 을 자주 조회하는 경우를 가정하고 created_at 을 이용한 index를 만들면 된다.

EXPLAIN 키워드를 사용하면 쿼리의 실행계획을 확인할 수 있다.
EXPLAIN SELECT * FROM post WHERE created_at > '2024-04-03';
해당 쿼리를 발생시켰다고 하면 어떤 key를 타고 탐색하는지 확인할 수 있다.

캐싱을 통한 성능 개선

인기 검색어등에 의해 특정 키워드에 검색이 집중되거나 상품 등록/삭제 API 호출과 조회 API의 호출 비율을 고려해서 Cache를 도입하는걸 고려할만 하다.

Cache를 사용하다보면 과거 데이터를 조회하는 사용자가 생길 수 있으니 등록/삭제/수정 API에 따라 Cache Eviction을 고려한다. Cache Eviction을 자주 사용하게 되면 Cache의 도입은 의미가 없어진다.

그리고 프로젝트는 Cache 도입을 먼저 요구했지만 Cache의 도입을 고려하는 맥락을 잘 이해해야 한다.

In-memory cache, Redis cache를 각각 구현해보며 진행이 됐다. In-memory cache는 spring-boot-starter-cache 의존성의 @Cacheable 을 사용한다.

인기 검색어를 사용할 때 Redis의 zSet을 사용해 count를 1씩 증가시키는 로직이 나왔다.

Pageable을 사용중이라면 Cacheable의 Key는 키워드와 PageNumber를 같이 사용해서 구분을 지어줘야 한다.

Cache Miss

Cache가 도입되어서 원래 데이터 조회를 바로 하던게 Cache를 조회하게 될 때 해당 캐시가 없다면 DB에서 조회 후 Cache에 조회한 데이터를 저장하는 것이 Cache Miss다.

오히려 과정이 늘어났으니 Cache Miss가 너무 많이 발생한다면 오히려 성능이 더 안좋아질 수도 있다.

Cache Hit

Cache에 있는 데이터를 바로 조회할 수 있으면 Cache Hit라고 한다. 과정만 보면 DB를 조회하든 Cache를 조회하든 네트워킹은 한번만 진행하는 것이지만 보통 더 빠르기 때문에 선택한다.

Local Cache와 Remote Cache

Local Cache는 인스턴스가 여러개로 Scale out 된다면 인스턴스간 데이터 동기화 문제가 발생하기 쉽다. 이를 해결한다면 쓰는 데에 문제 없지만 Remote Cache를 사용해 Scale out 한다면 동기화가 더 간편해진다.

Remote Cache로 사용 가능한 DB는 다양하고 Apache cassandra같은 DB를 쓸 수도 있지만 Redis를 쓴건 In-Memory, Key-Value, TTL, 레퍼런스가 많은 보편적인 인프라라는 장점등으로 Cache에 적합하다.

데이터의 변경이 거의 일어나지 않는다면 Local Cache가 더 좋은 선택이 될 수 있다.

nGrinder를 통한 성능 테스트

나는 이번 프로젝트에서 적은 학습곡선으로 GUI를 위해 JMeter를 사용했지만 nGrinder 또한 자주 추천되는 테스트 도구다.

nGrinder Controller는 실제로 요청을 날리는 Agent를 만들고 Target Server에 우리 실제 서버를 만들어 보낸다.

TPS: 1초에 몇개의 요청을 처리하는지
MTT: 하나의 요청에 몇 ms가 걸리는지

검색에 대해 Cache를 적용하고 안하고의 차이는 3~7배의 성능 향상을 보였다.

쓰레드를 늘려갈 때 TPS가 어느 순간을 기점으로 떨어진다면 마지막으로 향상한 부분을 포화 지점이라고 부른다. 해당 서비스가 거기까지 지원하기 좋게 설계되었다고 볼 수도 있다.

동시성 제어

우리 프로젝트는 선착순 쿠폰 발급 시나리오였기에 즉시 발급이 되어야 했고 이를 세션에서 즉시 피드백이 진행되어야 하기 때문에 Lock이 필요하다는 설명이 나왔다.

만약 쿠폰 발급을 신청제로 받아 나중에 추첨한다면 Lock은 사실상 필요 없다고 할 수 있다.

프로젝트 KPT 회고

Keep

  • 적절한 시간 분배
    • 쉬는 시간이 충분해서 공부할 때 집중하기 좋았다
  • 적당히 설정한 개발 스코프
    • 동시성 제어를 목표로 하는 프로젝트인 만큼 동시성 제어에 대한 공부에 집중할 수 있었다
  • 원활한 소통과 무난한 협업 과정
    • 협업 도구의 활용을 어렵지 않은 선에서 최대한 활용하여 개발 리소스를 아낌
    • 적은 개발 스코프 덕분에 페어 프로그래밍, 모두가 같이 이슈를 확인하는 일도 있었으나 각자 적절한 공부와 시도가 있었다
  • 좋은 팀 분위기
    • 공부로 피곤한 와중에도 팀 분위기는 좋게 유지됨

Problem

  • 성능 테스트를 진행했지만 테스트 결과를 해석하기 어려움
    • 동시성 과제인 만큼 성능 테스트도 진행하였으나 지표를 해석할 때 어려움을 겪음
    • 테스트 도구를 제대로 활용했는지도 확신을 가지기 어려움
  • Transactional의 사용에 어려움을 자주 겪음
    • Redis처럼 외부 시스템이 얹어지니까 Transactional을 더 예상하기 어려웠다

Try

  • 기술 스택을 더 다양하게 고민하고 공부해서 적용해볼 수 있으면 좋겠다
  • 우리가 개발한 로직의 성능 포화지점을 알아볼 수 있으면 좋겠다

0개의 댓글