본문 바로가기

개인 학습 메모장

(104)
성능 최적화 (DB 복제와 로드밸런싱) 지난 글에 이어 목표 TPS로 가기 위한 여정을 떠나보자. DB 복제 현재 question 조회에 대한 tps는 17.5인 상황이다. db 서버의 cpu가 매우 많이 오르는 것으로 보아 여전히 db가 병목이다. 이에 DB 서버를 한대 더 늘려 tps를 올려보도록 하자. RDS를 이용하고 있다면 읽기 전용 복제본을 생성하면 된다. 복제된 DB는 마스터 DB의 바이너리 로그를 읽어서 동기화 작업을 하는데, 방법에는 쿼리 기반으로 복제, 행 기반으로 복제, 두 방법을 혼합해서 복제 하는 방법이 있는데, 나는 RDS의 기본 값인 혼합하는 방식을 사용했다. 다른 방법이나 더 세밀한 설정을 하고 싶다면 파라미터 그룹의 설정을 변경하도록 하자. 코드 코드는 아래와 같다. 어플리케이션의 입장에서는 마스터, 슬레이브의 ..
성능 최적화 (스케일 업, 인덱스 튜닝) 목표 TPS 저번 글에서 시나리오를 통해 성능테스트를 진행해봤다. TPS는 13이 나왔고 목표했던 17 ~ 52에 한참 모자란 결과이다. 예상보다 TPS가 너무 나오지 않아 원인을 분석해본 결과 DB인 것으로 확인이 됐다. 그래서 팀원끼리 각자 맡은 도메인에 대해 쿼리를 개선해보기로 하고 다시 성능테스트를 해봤다. DB에 데이터는 10만건 들어있는 상태다. 먼저 시나리오에 포함되지 않은 읽기 쿼리들까지 포함해서 성능테스트를 해본 결과 다음과 같은 결과가 나왔다. 에러율은 낮지만 TPS는 4.7로 처참한 것을 확인할 수 있다. db는 RDS의 t3.micro를 사용하고 있었는데, cpu 사용량이 100퍼센트 가까히 찍히는 것을 확인할 수 있다. 단순히 인덱스 튜닝만으로는 해결할 수 없을 정도의 TPS와 R..
Ngrinder로 성능테스트 하기 계기 프로젝트가 거의 마무리 되고 조만간 프론트엔드 분들도 작업이 완료될 예정이라고 한다. 이에 따라 사용자를 받기 전에 목표하는 트래픽을 감당할 수 있을지 성능테스트를 해보고 필요하다면 로컬 캐시, etag, 인덱스를 태우거나 쿼리 튜닝을 하고자 한다. 목표하는 트래픽 잡기 내가 진행중인 프로젝트를 간단하게 소개하자면 지도에 사진, 평점 등과 같은 것들을 기록하고 일기를 작성하는 지도기반 커플 다이어리이다. 유사한 어플리케이션으로 커플 앱인 비트윈, 썸원이 있고 다이어리 어플인 timetreep이라는 어플리케이션이 있다. 이제 similarweb이라는 사이트에서 위 어플리케이션들이 얼마나 많은 트래픽을 받는지 확인하고 목표 트래픽을 잡아보자. 썸원인 경우 한달에 약 23만, 비트윈인 경우 한달에 약 1..
코드의 품질 관리를 도움 받기: SonarCloud, CodeMetrics SonarCloud 코드를 작성하다 보면 통용되는 컨벤션, 중복되는 코드, 보안 취약점 등을 인지하지 못한채 개발하게 된다. 심지어 Java를 C언어 처럼 사용한다거나 Go 언어를 Javascript처럼 사용하는 경우가 있을 것이다.(본인이 익숙한 언어에 맞게 다른 언어를 사용함) 이렇게 되면 새로운 언어를 배운다 하더라도 자신에게 익숙한 언어의 언어스타일로 개발을 하게 되는데 새로운 언어를 사용하는 의미 또한 많이 떨어질 것이다. 이러한 문제를 해결하기 위해 SonarCloud라는 코드 분석 오픈소스가 탄생하게 됐다. 품질관리 요소 이제 어떻게 품질을 관리하는지 알아보자 소나큐브가 코드를 분석하는 지표는 여기에 있다. Java를 기준으로 사용해본 결과 이펙티브 자바에서 강조하는 내용과 일치하는 부분이 ..
오랜만에 일기 어느덧 부트캠프에 들어온지 4개월이 지났다. 그 동안의 시간을 돌아봤을 때 정말 열심히 공부했고 다시 돌아가더라도 더 열심히 할 수는 없을 것 같다는 생각이다. 이렇게 공부를 열심히 할 수 있었던 배경에는 동료들이 있었기 때문인 것 같다. 고맙게도 동료들은 나를 믿고 질문을 많이 해줬으며 나 또한 그것을 보답하기 위해 많이 공부했고 실제로 어려운 개념을 쉬운 말로 설명 하는 과정은 큰 학습 효과를 줬다고 생각한다. 이렇게 동료와 함께 공부하고 친해지는 것이 부트 캠프의 가장 큰 장점이 아닐까 싶다. 공부한 내용이 쌓여가며 과거를 돌아봤을 때 나의 프로젝트는 헛점 투성이었고 지금의 내가 이 사람과 함께 일할 수 있을까? 라는 질문을 해봤다. 뽑을 사람이 없다면 그렇게 하겠지만 잘하는 사람들 많은데 굳이 눈..
우리의 문제 상황에 맞는 락 구현 요약 사용자가 여러개의 좌석을 선택한 상황에서 동시에 다른 사용자가 선택한 좌석과 겹치는 상황이 발생했을 때 어떻게 하면 사용자의 경험을 좋게하면서 최소한의 비용으로 이 상황을 극복할지에 관해 작성했다. 좌석을 선점(선택)할 때는 db를 사용하지 않았기 때문에 일반적인 락과는 다르게 접근해야 했으며, 레디스라는 캐시 서버에 특정 조건에 연산이 수행되지 않도록 하는 것이 문제 해결의 열쇠였다. 문제상황 문제 상황을 말하기에 앞서 예약을 하는 흐름은 다음과 같다. 매장을 선택한다. 매장에서 예약가능한 시간과 날짜를 선택한다 해당 날짜의 좌석을 선점한다. 예약 버튼을 누르면 선점한 좌석이 예약이 된다. 이를 코드로 보여주자면 아래와 같다. 문제의 코드 예약할 좌석의 상태를 캐싱해두는 코드 @Service @R..
이벤트 기반으로 책임 분리 확장성 있는 코드 확장성 이라는 개념에는 여러가지 요소가 있다. 기능의 확장 저장소의 확장 서버의 확장 기능의 확장 예를 들어 회원가입을 하면 회원가입 쿠폰을 뿌린다거나, 회원가입 쿠폰을 뿌리는 이벤트를 종료하는 상황이 있을 것이다. 저장소의 확장 데이터가 너무나도 많이 쌓여 RDB가 아닌 NoSQL로 저장소를 변경하는 상황이 발생하거나, 읽기 성능을 최적화 하기 위해 별도의 저장소를 사용하는 상황이 발생할 수 있을 것이다. 서버의 확장 특정 도메인에 사용자가 과도하게 몰려 도메인 별로 트래픽을 분산해야 하는 상황이 발생할 수 있을 것이다. 앞선 상황 이외에도 확장이라는 개념에는 또 다른 요소가 있을 수 있겠지만 나는 코딩을 할 때 위 3가지의 상황을 과하지 않게 예측하고 코드를 작성하려고 노력한다. (..
테이블 설계 글의 목적 테이블을 설계하는 것은 무척이나 어렵다. 복잡하고 동적인 현실 세계의 관계를 정적인 구조로 만드는 일은 수 많은 상황을 예측해야 하는 일이다. 테이블을 설계하며 한 고민의 과정을 정리함으로써 다음에는 좀 더 나은 생각을 할 수 있도록 글을 작성한다. 캐치 테이블의 테이블 구조 가장 크게 한 고민은 어떠한 요소를 필드로 둘지, 테이블로 둘지 두 결정 사이의 장단점을 비교하며 설계 당시에는 가장 나은 선택을 했다. 테이블을 설계할 때 가장 중요하게 여긴 가치 확장 (기능의 확장) 코드로 구현했을 때의 모습 (도메인을 분리해 다른 어플리케이션으로 작동할 수 있을지) 특이사항으로 실제 캐치테이블에서는 지원하지 않는 매장 내 테이블을 지정하여 예약을 하는 기능을 추가했다. (진짜 어려웠음) 복잡한 구조..