Search
Duplicate

최종 발표 대본

안녕하세요 저희는 탑스터 2.0을 기획한 힙스터즈 입니다.
저는 발표자 이태호입니다.
서비스 아키택쳐
CI/CD : 깃허브 액션스를 통해 트리거가 발동하면 DockerHub에 이미지를 빌드하고
S3에 docker compose파일을 포함한 파일들을 zip파일로 업로드합니다. 그리고 EB에 해당 zip파일을 수행할 것을 지시한다.
저희 프로젝트의 RDB로는 MySQL을, NoSQL으로 Redis를 사용하고 있습니다.
음악검색을 위해 SpotifyOpenAPI를 이용했습니다.
4-1 Redis
저희는 Redis를 이용해 데이터 캐싱, 리프래시 토큰을 저장하고 있습니다.
data caching
7번 페이지
데이터 캐싱을 통해 응답속도를 향상 시킬 수 있었습니다.
8번 페이지
캐싱 되지 않은 데이터는 1.4초의 응답시간이 걸렸습니다.
캐싱된 데이터는 18ms가 걸려 약 78배의 성능 향상을 확인 할 수 있었습니다.
외부 API요청시 비용이 부과됩니다. 따라서 API 요청의 횟수를 줄이기 위해 Data Caching을 도입했습니다.
9번 페이지
캐싱전략응로는 LRU를 선택했습니다.
서비스 특성상 자주 요청되는 앨범은 특정되어 있기 때문에, 자주 요청되는 앨범이 늦게 지워지고, 빈도수가 낮은 앨범이 먼저 지워질 수 있도록 LRU 캐싱전략을 선택했습니다.
10번 페이지
토큰 기반 인증 방식은 토큰이 탈취 당했을 때 통제권을 잃는다는 단점이 있습니다.
Access 토큰의 만료기한을 짧게 주고, refresh 토큰의 만료기한을 길게 주어 refresh 토큰으로 Access token을 발급 받게 햇습니다. refresh 토큰을 레디스에 저장했습니다.
redis는 key-value 형태의 데이터를 담기 때문에, key로는 refresh 토큰값을, value로 유저의 유니크 값인 유저 네임을 넣었습니다.
11번 페이지
EB vs ECS
도커 컨테이너를 이용한 배포를 하기 위해 엘라스틱 빈스토크와 ECS를 고려했습니다.
이중 저희는 엘라스틱 빈스토크를 채택했고, 가장 큰 이유는 러닝커브가 완만해서 였습니다.
ECS를 사용하기 위해서는 클러스터, 서비스, 태스크 대피니션, 동적포트 매핑과 같은 설정들에 대한 기반 지식이 추가적으로 필요했습니다.
하지만 저희 프로젝트 기간이 짧아, 시간적 여유가 없어 엘라스틱 빈스토크를 채용했습니다.
12~15 페이지
RestClient
기존에는 RestTemplate을 이용해 서버간 통신을 했습니다. 하지만 RestTemplate은 클래스 내부에서 더이상 지원하지 않으니 동기식인 RestClient 혹은 비동기식인 WebClient를 권장했습니다.
WebCLient는 WebFlux의존성을 추가해야하기 때문에 별도의 의존성 추가가 필요 없는 RestClient로 선택을 했습니다.
ResetCLient는 메소드 체이닝 방식을 이용해 코드 가독성을 올릴 수 있었습니다.
18 페이지
Facade Pattern
Topster를 생성하고, 저장할 때 연관관계를 맺는 TopsterALbum과 ALbum도 추가적으로 생성하고 저장해야 합니다.
기존의 방식에서는 TopsterService안에서 Album과 TopsterAlbum을 생성/저장을 하는 방식이었습니다. 하지만 이는 모듈간 강한 결합을 맺게 되고, 변경에 취약합니다.
저희는 FAcade Pattern을 도입해 Topster를 생성하는 흐름을 담당하는 클래스를 추가했습니다. 이를 통해 모듈간에 결합도를 낮출 수 있었으며, test코드도 작성하기 쉬워졌습니다.
20 페이지
조회 성능 최적화
서버 부하 테스트를 위해 로컬에서 JMeter를 이용해 테스트를 진행했습니다.
30초 동안 2만건의 데이터를 받아오는 테스트를 진행을 했을 때, error율이 36퍼센트, 응답속도가 387ms이었습니다.
저희가 분석한 에러 이유는 JPA의 N+1이었습니다.
서버부하에 대응하기 위해 저희는 조회 성능 최적화를 진행했습니다.
21 페이지
페이징 처리를 통해 한번 요청에 9개의 Topster를 조회할 수 있도록 변경했습니다.
배치사이즈를 설정해 N+1문제를 해결할 수 있었씁니다.
쿼리 최적화를 통해 서버부하에 대응할 수 있었씁니다.
22
스포티파이의 access token을 발급받는데 어려움이 있었습니다. 저희는 MVP를 완성하기 위해 임시방편으로 ManiaDb라는 쉬운 Api를 사용했습니다. ManiaDb엔 많은 단점이 있다는 것을 인지 후 향후 Spotify를 사용할 것을 계획했습니다.
maniaDB에서 스포티파이로 쉽게 이식하기 위해서 OpenApi라는 인터페이스를 만들어서 추상화를 진행했습니다.
maniaDB는 Spotify에 비해 약 3.35배 가량 느린 응답속도를 가졋습니다. 따라서 MVP 달성 후 저희는 maniaDB에서 Spotify로 변경하기로 결정했습니다. Spring의 @Primary @퀄리파이어 어노테이션을 이용해 Bean을 관리했고,  SpotifyAPI를 사용하게 됐을 때 AlbumService는 한줄의 코드변경 없이 이식에 성공했습니다.
추가적으로 써드파티에 장애가 생겼을 때 다른 써드파티를 이용해 장애를 극복할 수 있다는 장점도 있습니다.
28 페이지
저희 프로젝트에 알림 기능을 추가하는것을 도전 중입니다. SSE를 통해 로컬 환경에서 알림 서비스를 구현을 했습니다.하지만 저희 프로젝트 기간이 짧아 프론트엔드 페이지를 만들지 못해 아직 운영 환경에 도입하지 못한 상태입니다.팀원들간 코드리뷰와 리팩토링을 거쳐 완성도 있게 구현할 예정입니다.
////////////////////////////////////////////// ////////////////////////////////////////////// ////////////////////////////////////////////// /////////////////////////////////////////////
Spotify API를 통한 구현에 어려움을 겪어 일단 서비스를 배포하기위해(또는 MVP를 완성시키기 위해) ManiaDb라는 쉬운 Api를 사용했고
ManiaDb에는 많은 자료가 없는 것을 알아서 향후 Spotify를 사용할 것이라고 계획해뒀기 때문에
쉽게 변경하기 위해서 OpenApi라는 인터페이스를 만들어서 추상화를 진행했고, 스포티파이 API를 통해 구현했을 때
AlbumService의 코드 변경없이 쉽게 이식할 수 있었다는 내용이 더 와닿지 않을까
어짜피 spotify로 넘어갈 거라서 openAPIService를 추상화 했다. maniadb는 임시방편이였다. 그래서 편하게 할 수 있었다.