전체 글 35

저장소와 검색 (2)

트랜잭션 처리와 분산 일반적인 온라인 어플리케이션에서는 여러 종류의 데이터가 사용자 입력을 기반으로 삽입되거나 갱신된다. 이는 클라이언트와 서버 간의 대화식이기에, 이 접근 패턴을 온라인 트랜잭션 처리( online transaction processing, OLTP )라고 한다. OLTP는 이익을 산출하는 비즈니스에 맞닿아 있기에 대부분의 데이터 베이스는 OLTP 에 맞추어 설계되고 발전되었다.  하지만 시간이 지남에 따라 사람들은 데이터 베이스를 "데이터 분석 ( data analytic )" 목적으로도 많이 사용하기 시작했다. 데이터 분석은 기존 트랜잭션과 접근 패턴이 매우 다르다. 분석에 사용되는 쿼리는 사용자에게 원시 데이터만을 반환하지 않고, 많은 수의 레코드에 대한 집계 통계를 계산해야 했기..

저장소와 검색 (1)

이 장에서는 데이터베이스가 저장과 검색을 내부적으로 어떻게 처리하는지에 대해 다룬다. JPA나 Typeorm 과 같은 ORM을 사용하는 애플리케이션 개발자들이 이를 알아야하는 이유는 처음부터 자신의 저장소 엔진을 구현하기 위해서라기 보다는 여러 저장소 엔진 중에 애플리케이션에 가장 적합한 엔진을 선택하기 위함이다. 관계형 데이터베이스와 NoSQL 데이터베이스의 저장소 엔진, 그리고 로그 구조 계열 저장소 엔진과 (B-Tree와 같은) 페이지 지향 계열 저장소 엔진을 검토해보도록 하자.  데이터베이스를 강력하게 만드는 데이터 구조 아래와 같은 아주 간단한 데이터베이스를 가정해보자. #!/bin/bashdb_set () { echo "$1,$2" >> database}db_get () { grep "^$1,..

데이터 모델과 질의 언어

내 언어의 한계는 내 세계의 한계를 의미한다.- 루트비히 비트겐슈타인, 논리-철학 논고(1922) 요즘 개발 커뮤니티에서 "요즘 어플리케이션들이 AI Wrapper 다"라는 이야기를 심심치 않게 들을 수 있다. 이곳 저곳에 생성형 AI 관련 기능을 넣으면서 나온 이야기인듯 한데.. 결국 기존 어플리케이션도 Database Wrapper가 아니냐는 이야기로 귀결된다. 그만큼 현재 데이터 베이스 모델들은 각종 ORM 혹은 데이터 베이스 콘솔이나 CLI 등으로 잘 추상화가 되어 있어서 개발자들은 이들을 사용하는데 불편함을 느끼지 못한다. 데이터 모델은 다양한 유형을 갖고 있고, 각 유형마다 어떤 연산은 빠르게 어떤 연산은 매우 느리게 동작하기도 한다.이 장에서는 다양한 데이터 모델 및 그들의 질의 언어 ( Q..

신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션 (2)

확장성 부하 기술하기 성능 저하를 유발하는 흔한 이유 중 하나는 부하 증가다. 확장성은 증가한 부하에 대처하는 시스템 능력을 설명하는 데 사용하는 용어지만 시스템에 부여하는 일차원적인 표식은 아니다. 단순은 "~은 확장 가능하다" 와 같은 말은 의미가 없다. 오히려 확장성을 논한다는 것은 "시스템이 특정 방식으로 커지면 이를 대처하기 위한 좋은 조치는 무엇일까", "추가 부하를 다루기 위해 계산 자원을 어떻게 투입할까" 같은 질문을 고려한다는 의미다. 저자는 트위터의 트윗 처리 방식을 대표적인 예시로 말한다.  트위터의 주요 동작은 크게 두 가지, (1) 트윗 작성과 (2) 홈 타임라인 조회이다. 트윗 작성은 초당 46,000번 발생하고, 홈 타임라인 조회는 초당 300,000번 발생한다. 사실 이 정도..

신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션 (1)

오늘날 많은 애플리케이션은 계산 중심보다는 데이터 중심적이다. 고도의 계산으로 인해 CPU의 성능이 중요하기보다는 많고 복잡하며 변화하는 데이터를 잘 다루는 데에 애플리케이션의 방점이 찍혀있다.  이 책은 데이터 시스템의 원칙과 실용성, 그리고 이를 활용한 데이터 중심 애플리케이션을 개발하는 방법을 모두 담고 있다. 책에서 소개된 다양한 도구가 공통으로 지닌 것은 무엇이고 서로 구별되는 것은 무엇인지, 그리고 어떻게 그러한 특성을 구현해냈는지 알아보도록 한다. 데이터 시스템에 대한 생각 일반적으로 데이터 시스템은 데이터베이스, 큐, 캐시 등 다른 범주의 도구들을 모두 포괄하는 용어이다. 그런 포괄적인 용어를 사용하는 데에는 두 가지 이유가 있다. 1. 최근에 등장한 도구들은 다양한 사용 사례(use-ca..

단위 테스트란 무엇인가

단위 테스트의 정의 단위 테스트의 가장 중요한 세 가지 속성은 아래와 같다. 1. 작은 코드 조각을 검증하고, 2. 빠르게 수행하고, 3. 격리된 방식으로 처리하는 자동화된 테스트 처음 두 가지 속성은 대체로 논란의 여지가 없지만, 마지막 속성인 '격리 문제'는 단위 테스트의 고전파와 런던파를 구분하는 근원이 된다. 격리 문제에 대한 런던파의 접근 런던파에서는 '테스트의 격리 방식'을 '테스트 대상 시스템을 협력자 ( collaborator )에게서 격리하는 것'으로 규정한다. 즉, 하나의 클래스가 다른 클래스들에 의존하면 모든 의존성을 테스트 대역 ( test double )로 대체해야한다. 이 방법의 이점 중 하나는 테스트가 실패하면 코드베이스의 어느 부분이 고장 났는지 확실히 알 수 있다는 것이다...

MySQL 복제 (2)

복제 Failover 복제는 고가용성의 초석이다. 데이터 복사본을 다른 위치에서 지속적으로 업데이트하면 백업으로 이동하는 것보다 재해로부터 복구하는 것이 훨씬 쉽다. 여기에서는 레플리카를 원본 노드로 승격하는 올바른 방법에 대해 설명한다. "레플리카 승격"과 "Failover"가 동의어임에 유의하자. 두 가지 모두 쓰기를 수행하지 못하도록 소스를 강등시키고 레플리카를 소스 역할로 승격시키는 작업을 의미한다. 계획된 승격 일반적으로 승격은 유지 관리 이벤트( 보안 패치, 커널 업데이트, 재시작을 해야하는 몇 가지 구성 옵션으로 인한 재시작 등 )로 인해 수행된다. 이러한 유형의 승격을 계획된 승격이라고 한다. 이 승격을 성공적으로 처리하기 위해 다음 단계를 수행한다. 1. 승격할 레플리카를 결정한다. 대개..

MySQL 복제 (1)

개요 MySQL 의 복제 기능은 소위 "스케일 아웃"이라는 아키텍처를 사용하는 고성능 애플리케이션의 기반이 된다. 복제를 통해 하나 이상의 서버를 다른 서버의 레플리카로 구성하여 데이터를 소스 복사본과 동기화할 수 있다. 이는 고성능 애플리케이션에 유용할 뿐만 아니라 고가용성, 확장성, 재해 복구, 백업, 분석, 데이터 웨어하우징 등 여러 작업을 위한 초석이 되기도 한다. 복제는 대략적인 과정은 다음과 같다. 소스 서버의 로그에 데이터 또는 데이터 구조를 수정하는 이벤트를 기록한다. 그러면 레플리카 서버는 소스의 로그에서 이벤트를 읽고 재생할 수 있다. 당연히 이렇게 되면 실시간과 레플리카에 표시된 시간 사이의 지연 ( 레플리카 지연 )이 발생하고, 이는 쿼리의 규모에 따라 몇 초, 몇 분 또는 몇 시간..

Jira web request 에러

Jira automation을 구성하던 중 에러가 발생했다. 본디 목적은 티켓이 특정 상태로 이동할 때, 웹 훅을 통한 깃 작업을 수행하는 것이었는데 웹 훅 요청에 대한 응답이 아래와 같이 403으로 반환되었다. 경우에 따라서는 "발신 웹 요청 구성이 유효하지 않습니다. 다음 오류를 수정하고 다시 시도하세요. 유효하지 않은 웹 요청 URL: https://~~" 이라는 에러 문구가 나타나기도 한다. Server: squid Mime-Version: 1.0 Date: Thu, 07 Dec 2023 15:08:48 GMT Content-Type: text/html;charset=utf-8 Content-Length: 3090 X-Squid-Error: ERR_ACCESS_DENIED 0 Vary: Accep..

Jira 2023.12.08

MYSQL HA & DR 토폴로지 - 토스ㅣSLASH 21

스크립트 바로가기: https://daglo.ai/share/f6L9Z-uv_szFXfbs 토스 데이터베이스의 HA 및 DR 솔루션에 대해 설명해 주세요. MMM은 MySQL Multi-Master Replication Manager의 약자로 토스 Live SQL 데이터베이스 HA 솔루션으로 사용되고 있다. 구글에서 개발한 솔루션이었으나, 현재는 업데이트가 중단되어 필요에 따라 자체 업데이트를 하며 운영하고 있다. 토스 데이터베이스는 마스터-마스터 노드로 구성되며, MMM을 통해 서로 데이터를 복제한다. 모니터링 데몬은 각 데이터베이스 서버에서 실행되며, 서비스 IP는 MMM 데이터베이스 롤 변경에 따라 이동되어, 애플리케이션 서버에 페일오버한다. 모니터링 항목은 4가지이며 이상이 있을 시 MMM이 스텐..

Database 2023.12.06

커버리지 지표 ( coverage metrix )

테스트 스위트 품질 측정을 위한 커버리지 지표 커버리지 지표란? 커버리지 지표는 테스트 스위트가 소스 코드를 얼마나 실행하는지를 백분율로 나타낸다. 일반적으로 커버리지 지표의 커버리지 숫자가 높을 수록 더 좋다고 알려져있지만, 사실 이것은 그리 간단하지 않다. 커버리지 지표는 중요한 피드백을 주더라도 테스트 스위트 품질을 효과적으로 측정하는 데 사용될 수 없다. 코드 커버리지가 너무 적을 때 ( 약 10% 미만 )는, 테스트가 충분치 않다는 좋은 증거이지만, 100 % 커버리지라고 해서 반드시 양질의 테스트 스위트를 보장하지는 않는다. 높은 커버리지의 테스트 스위트도 품질이 떨어질 수 있다. 코드 커버리지 지표에 대한 이해 가장 많이 이용되는 커버리지 지표는 "코드 커버리지( code coverage )..

단위 테스트의 목표

개요 단위 테스트를 배운다는 것은 테스트 프레임 워크나 목 라이브러리 등과 같은 기술적인 부분을 익히는 것에 그치지 않는다. 단위 테스트는 단순히 테스트를 작성하는 것보다 더 큰 범주이다. 테스트에 드는 노력을 가능한 한 줄이고 그에 따르는 이득을 최대화해야 한다. 두 가지를 모두 달성하기란 쉽지 않다. 단위 테스트 현황 지난 20년간 단위 테스트를 적용할 것을 독려하는 분위기가 자리 잡았으며, 대부분의 프로그래머는 단위 테스트를 실천하고 중요성을 알고 있다. 그냥 쓰고 버리는 프로젝트가 아니라면, 단위 테스트는 늘 적용해야 한다. 기업용 애플리케이션 개발 프로젝트는 거의 모두 단위 테스트가 적용되어 있으며, 제품 코드와 테스트 코드의 비율은 1:1에서 1:3 ( 제품 코드 한 줄 : 테스트 코드 세 줄..

Unit Testing (Vladimir Khorikov) 책을 리뷰하기 전

단위 테스트의 중요성은 개발을 공부한 이후부터 줄곧 들어왔다. 하지만 실무에서 개발을 하다보면 단위 테스트에 대한 여러 가지 질문이 생각난다. - 좋은 단위 테스트가 뭐지? 내가 작성한 것도 좋은 단위 테스트인가? - 테스트하고자 하는 것이 너무나 단순해서 결과가 자명한 경우에도 테스트 코드를 짜는 것이 필요할까? - 모든 함수를 테스트해야하는가? 일부만 테스트해도 된다면, 어디까지 테스트 코드를 짜는 것이 바람직할까? 이러한 질문들의 답을 찾기 위한 과정으로, 블라디미르 코리코프의 Unit Test ( 단위 테스트 | 생산성과 품질을 위한 단위 테스트 원칙과 패턴 )을 읽게 되었다. 이 책의 구성은 크게 다음과 같다. 1. 단위 테스트의 목표를 정의 / 좋은 테스트와 좋지 않은 테스트를 구별하는 방법 ..

쿼리 성능 최적화 (2)

쿼리를 재구성하는 방법 문제가 있는 쿼리를 최적화할 때는, 원하는 결과를 얻을 수 있는 다른 쿼리를 구성하는 것이 좋지만 반드시 원하는 결과와 동일한 데이터를 산출하는 쿼리를 고집할 필요는 없다. 효율성이 향상된다면 쿼리를 다시 작성하여 약간은 다른 결과를 검색하고, 궁극적으로 애플리케이션 코드를 통해 성능을 향상 시킬 수 있다. 이 섹션에서는 광범위한 쿼리를 재구성하는 데 도움이 되는 기법에 대해 설명하고 각 기법을 언제 사용하는지에 대해 설명하고자 한다. 복잡한 쿼리 vs 많은 쿼리 쿼리 설계에 대한 중요한 질문은 "복잡한 쿼리를 여러 개의 단순한 쿼리로 분할하는 것이 더 나은지 여부"이다. 데이터베이스 설계에 대한 전통적인 접근 방식은 가능한 한 적은 쿼리로 최대한 많은 작업을 수행하는 것을 강조했..

쿼리 성능 최적화 (1)

쿼리가 느린 이유 빠른 쿼리의 핵심은 당연히도 실행 시간에 있다. 쿼리는 작업이지만, 하위 작업으로 구성되며 이러한 하위 작업은 모두 시간을 소모한다. 결국 쿼리를 최적화하기 위해서는 하위 작업을 (1) 제거하거나, (2) 발생 횟수를 줄이거나 (3) 더 빠르게 수행하여 최적화해야한다. 일반적으로 클라이언트로부터 서버까지의 쿼리의 ( 아주 대략적인 ) 라이프 사이클은 구문 분석, 계획 실행 후 다시 클라이언트로 돌아가는 것으로 이루어진다. 여기서 실행은 쿼리의 수명 중 가장 중요한 단계이며, 이 작업에서 스토리지 엔진에 대한 많은 호출과 그룹화 및 정렬과 같은 검색 후 작업이 이루어진다. 이 모든 작업을 수행하는 동안 쿼리는 네트워크, CPU 및 통계, 계획, 잠금 등의 작업에 시간을 소비하며, 특히 행..

Gitlab 에서 Github 로의 마이그레이션 ( MR to PR )

개요 회사에서 Git 저장소를 Gitlab에서 Github로 이전하게 되었다. 마이그레이션 방법과 유의점에 대해 적어보고자 한다. 시작하기 전, 본 마이그레이션 방법은 큰 조직에는 그리 유용하지 않을 수 있다는 점을 미리 말한다. 지속적으로 MR 이 올라오고 이에 따라 배포가 이루어져야만 하는 조직에서는 Gitlab에서의 계속되는 변화를 Continuos 하게 Github로 옮기기 위해 미러링 등의 방법을 고려해야 한다. 필자의 조직( 백엔드팀 )은 5명 내외의 크지 않은 조직이기에, 팀원들에게 양해를 구하고 잠시 Gitlab으로 MR 올리는 것을 중지해달라는 양해를 구하고 마이그레이션을 진행하였다. Repsoitory 마이그레이션 Repository 마이그레이션은 간단하게 진행하였다. 현재는 로컬 저장..

Git 2023.11.11

고성능을 위한 인덱싱 (2)

앞선 고성능을 위한 인덱싱 (1) 에서는 다양한 유형의 인덱스를 소개하고, 유의할 점들을 살펴보았다. 이곳에서는 이런 인덱스들을 실제로 활용하고 최적화하는 방법에 대해 살펴본다. 고성능을 위한 인덱싱 전략 Prefix 인덱스 및 인덱스 선택성 인덱싱도 결국 비용이다. 데이터가 크기가 클수록 인덱스의 크기는 커진다. 이 때, 전체 값 대신 앞의 몇 개의 문자를 인덱싱 하면 공간을 절약하고 성능을 향상시킬 수 있다. "앞의 몇 개"의 기준은 총 데이터의 갯수 (#T)에 대한 고유한 데이터의 갯수(Cardinality)의 비율에 따라 달라진다. Cardinality / #T 의 값은 1 / #T부터 1까지의 스펙트럼을 지니며, 1에 가까울수록 훌륭한 인덱스 선택이 된다. 즉, 데이터의 고유성이 보장되는 범위 ..

고성능을 위한 인덱싱 (1)

개요 인덱스란, 스토리지 엔진이 행을 빠르게 찾기 위해 사용하는 데이터 구조이다. 인덱스는 우수한 성능을 위해 매우 중요하며, 데이터가 커질수록 더더욱 중요하다. 잘못된 인덱싱의 사용은 실제 성능 문제의 주요 원인이 되기도 한다. 인덱스 최적화는 쿼리 성능을 향상시키는 가장 강력한 방법이다. 인덱스는 성능을 수십 배나 향상시킬 수 있으며 최적의 인덱스는 때때로 단순히 양호한 인덱스보다 성능을 2배 정도 향상 시킬 수 있다. 인덱싱 기본 MySQL에서 인덱스가 어떻게 작동하는지 이해하는 가장 쉬운 방법은 책의 색인을 떠올리는 것이다. 책에서 특정 주제에 대해 찾고 싶다면, 색인을 펴서 주제를 논하는 페이지 번호를 찾고, 해당 페이지로 이동하면 된다. MySQL 스토리지 엔진은 비슷한 방식으로 인덱스를 사용..

스키마 설계와 관리

서론 논리적, 물리적으로 우수한 설계는 고성능 쿼리의 기반이 된다. 스키마 설계는 중요하지만, 때때로 트레이드 오프를 피하기 어렵기도 하다. 가령, 비정규화된 스키마는 일부 쿼리의 속도를 높일 수 있지만, 다른 쿼리의 성능에 영향을 줄 수 있다. 카운터 및 요약 테이블을 추가하는 것이 쿼리 최적화에 도움이 될 수는 있지만, 유지 보수에 비용이 많이 들 수 있다. 따라서, 이번 장에서는 MySQL 에서 스키마 설계 시 어떤 사항들을 유의해야 하는지 살펴보고자 한다. 최적의 데이터 유형 선택 MySQL은 다양한 데이터 유형을 지원하고, 성능 향상과 리소스의 낭비를 줄이기 위해서는 적절한 데이터 유형을 선택해야 한다. 다만, 아래의 간단한 지침들은 데이터 유형과는 무관하게 더 나은 설계를 하는 데에 도움을 준..

AMQP & RabbitMQ

1. 개요 RabbitMQ is the most widely deployed open source message broker. - RabbitMQ 공식 홈페이지 RabbitMQ를 구글에 검색하면 가장 상단에 나오는 내용이다. 일반적으로 블로그에서는 RabbitMQ를 간단하게 “AMQP를 구현한 오픈소스 메세지 브로커“ 정도로 정의한다. 위 정의를 보고 RabbitMQ가 무엇인지 단박에 알 수 있는 사람은 이 글을 보고 있지 않을 것이다. AMQP는 무엇이고, 메세지는 무엇이며 브로커는 무엇인지 궁금증이 들기 마련이다. 큐에 대한 기본적인 개념 나아가 AMQP부터 정리하며, 최종적으로 RabbitMQ가 어떤 녀석인지 알아보자. 2. AMQP ( Advanced Message Queue Protocol ) ..

Protocol 2023.09.18