데이터베이스 레플리케이션 (Database Replication)
한눈에 보기
원본 데이터베이스의 변경을 레플리카에 복제해 읽기 부하와 장애를 분산하는 구조를 다룬다. 동기와 비동기 복제, 복제 지연, 읽기 일관성과 장애 전환을 정리했다.
최종 업데이트 2026.09.17
데이터베이스 레플리케이션(Replication)은 하나의 원본 데이터베이스에 일어난 변경을 다른 서버들에 복제하여 같은 데이터를 여러 곳에 유지하는 기술이다. 쓰기를 담당하는 소스(source)와 복제본을 유지하는 레플리카(replica)로 역할을 나누면 읽기 부하를 분산하고, 장애 시 레플리카를 새 소스로 승격해 서비스를 이어갈 수 있다. 다만 복제에는 지연이 따르므로 읽기 일관성 문제를 함께 이해해야 한다.
소스-레플리카 구조
가장 널리 쓰이는 구성은 소스 하나에 레플리카 여러 대를 붙이는 단일 리더(single leader) 구조다. 모든 쓰기(INSERT, UPDATE, DELETE)는 소스로만 들어가고, 레플리카는 소스의 변경 기록을 받아 같은 순서로 재실행한다. MySQL을 예로 들면 흐름은 다음과 같다.
- 소스가 트랜잭션을 커밋하면서 변경 내용을 바이너리 로그(binary log)에 기록한다.
- 레플리카의 IO 스레드가 소스에 접속해 바이너리 로그를 받아 자신의 릴레이 로그(relay log)에 저장한다.
- 레플리카의 SQL 스레드가 릴레이 로그를 읽어 변경을 자신의 데이터에 적용한다.
이 구조의 장점은 명확하다. 대부분의 서비스는 읽기 비율이 쓰기보다 압도적으로 높으므로, 읽기 쿼리를 레플리카 여러 대로 흩어 보내면 소스의 부담이 크게 줄어든다. 또 레플리카는 백업을 뜨는 용도나 무거운 분석 쿼리를 격리하는 용도로도 쓰인다. 반면 쓰기는 여전히 소스 한 대에 몰리므로, 쓰기 처리량 자체를 늘리려면 레플리케이션이 아니라 샤딩 같은 다른 수단이 필요하다.
동기 복제와 비동기 복제
복제 방식은 소스가 커밋을 완료했다고 응답하는 시점에 따라 나뉜다.
| 구분 | 동기(synchronous) | 반동기(semi-synchronous) | 비동기(asynchronous) |
|---|---|---|---|
| 커밋 완료 시점 | 모든 레플리카 적용 확인 후 | 최소 한 대가 로그 수신 확인 후 | 소스 기록 즉시 |
| 쓰기 지연 | 가장 크다 | 중간 | 가장 작다 |
| 데이터 유실 위험 | 없음 | 거의 없음 | 소스 장애 시 미전송분 유실 가능 |
| 레플리카 장애 영향 | 쓰기가 함께 멈출 수 있다 | 제한적 | 없음 |
완전 동기 복제는 레플리카 한 대가 느려지거나 죽으면 소스의 쓰기까지 멈출 수 있어 실무에서 그대로 쓰이는 일은 드물다. 그래서 대부분의 시스템은 비동기를 기본으로 하되, 유실을 줄여야 하는 곳에서 반동기를 택한다. 반동기는 레플리카가 변경을 적용까지 했다는 보장이 아니라 로그를 받았다는 보장이라는 점도 구분해서 알아 두어야 한다.
복제 지연과 읽기 일관성 문제
비동기 복제에서는 소스와 레플리카 사이에 복제 지연(replication lag)이 존재한다. 평소에는 밀리초 수준이지만, 대량 배치 작업이나 레플리카의 부하에 따라 수 초에서 수 분까지 벌어질 수 있다. 이때 대표적으로 다음 문제가 생긴다.
- 내가 쓴 글이 안 보이는 문제. 사용자가 글을 저장(소스에 쓰기)한 직후 목록을 조회(레플리카에서 읽기)하면 방금 쓴 글이 없는 것처럼 보인다. 자신의 쓰기 읽기(read-your-writes) 일관성이 깨진 것이다.
- 시간이 거꾸로 가는 문제. 지연이 서로 다른 레플리카를 번갈아 읽으면 새 데이터를 봤다가 다시 옛 데이터를 보게 된다. 단조 읽기(monotonic reads)가 깨진 경우다.
대응 방법으로는 쓰기 직후 일정 시간 동안 해당 사용자의 읽기를 소스로 보내는 방법, 세션을 특정 레플리카에 고정하는 방법, 최신성이 중요한 조회(결제 내역, 방금 수정한 프로필 등)는 아예 소스에서 읽도록 라우팅을 나누는 방법이 쓰인다. 어떤 조회가 최신성을 요구하고 어떤 조회가 약간의 지연을 허용하는지 구분하는 것이 설계의 핵심이다.
페일오버
소스에 장애가 나면 레플리카 중 하나를 새 소스로 승격(promotion)하는 페일오버(failover)를 수행한다. 절차는 장애 감지, 가장 최신 데이터를 가진 레플리카 선정, 승격, 애플리케이션과 나머지 레플리카가 새 소스를 바라보도록 전환하는 순서로 진행된다. 단순해 보이지만 함정이 많다.
- 비동기 복제였다면 옛 소스에는 커밋됐지만 레플리카에는 도달하지 못한 트랜잭션이 유실될 수 있다.
- 옛 소스가 죽은 것이 아니라 네트워크만 끊겼던 경우, 복구 후 소스가 두 대가 되는 스플릿 브레인(split brain)이 발생해 데이터가 갈라질 수 있다.
- 장애 감지 타임아웃을 너무 짧게 잡으면 일시적 부하를 장애로 오판해 불필요한 페일오버가 반복된다.
그래서 실무에서는 수동 페일오버를 택하거나, 자동화하더라도 옛 소스를 확실히 격리(fencing)하는 장치를 함께 둔다. 페일오버를 감안하면 레플리카는 읽기 분산 장치이자 동시에 고가용성(High Availability)을 위한 대기 서버인 셈이다.
면접에서 이렇게 물어본다
- 레플리케이션을 도입하는 목적을 읽기 분산과 가용성 관점에서 설명해 보라.
- 동기, 반동기, 비동기 복제의 차이와 각각의 트레이드오프는 무엇인가.
- 사용자가 글을 저장한 직후 목록에 글이 안 보이는 현상의 원인과 해결책을 말해 보라.
- 소스 장애 시 페일오버 과정에서 생길 수 있는 문제를 아는 대로 설명해 보라.
- 레플리케이션으로 해결되지 않는 확장 문제는 무엇이고, 그때는 무엇을 검토해야 하는가.
데이터베이스에서 같이 읽기
- 이상 현상 (Anomaly)이상 현상은 테이블 설계가 잘못되어 삽입, 갱신, 삭제 과정에서 데이터 불일치나 손실이 생기는 현상이다. 삽입, 갱신, 삭제 이상의 세 종류와 원인인 함수 종속, 해결책인 정규화까지 예시와 함께 정리한다.
- 데이터베이스 커넥션 풀 (Database Connection Pool)데이터베이스 연결을 미리 만들어 재사용하는 커넥션 풀의 동작 원리와 필요성을 다룬다. HikariCP 설정, 풀 크기 계산, 타임아웃과 고갈 문제를 실무 관점에서 정리했다.
- 인덱스 (Index)인덱스는 컬럼 값과 저장 위치를 별도 자료구조로 정리해 검색 속도를 높이는 장치다. B+Tree 동작 원리, 클러스터드와 논클러스터드 비교, 복합 인덱스와 커버링 인덱스, 설계 시 주의점을 다룬다.
- 데이터베이스 키 (Key)의 종류데이터베이스 키는 행을 유일하게 식별하거나 테이블 간 관계를 표현하는 속성 집합이다. 유일성과 최소성을 기준으로 슈퍼키, 후보키, 기본키, 대체키, 외래키를 구분하고 자연키와 대리키 선택 기준까지 정리한다.
이 개념, 내 코드에서는 어떻게 물어볼까요
데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.
공고 넣고 시작하기