복제
Replication
방법
같은 데이터를 여러 서버에 복사해 두고 변경을 계속 따라가게 만들어 읽기와 장애 대비를 나누는 방식입니다.
등장 배경
데이터를 서버 한 대에 모아 두면 관리가 단순합니다. 어디에 무엇이 있는지 고민할 일이 없고, 값이 어긋날 걱정도 없습니다. 규모가 작을 때는 이 편이 낫습니다.
그 한 대에 두 가지가 걸립니다. 하나는 읽기가 몰리는 일입니다. 페이지덱에서 전체 요청의 8할이 문서 목록을 불러오는 조회였습니다. 월요일 아침에 사람들이 한꺼번에 들어오면 조회가 밀리고, 같은 서버가 저장도 받으니 저장 버튼을 누른 사람까지 함께 기다렸습니다.
다른 하나는 그 한 대가 멈추는 일입니다. 저장 장치가 고장 난 날 두 시간 동안 아무 문서도 열리지 않았습니다. 백업은 있었지만 복구에 그만큼이 걸렸습니다. 서버 한 대가 곧 서비스의 수명이 되는 구조였던 것입니다.
두 문제의 답이 같은 방향에 있었습니다. 같은 데이터를 다른 서버에도 두는 것입니다. 사본이 있으면 읽기를 나눠 보낼 수 있고, 원본이 죽어도 사본이 그 자리를 이어받을 수 있습니다. 대신 사본이 원본과 같은 상태를 유지하도록 계속 맞춰 주어야 하고, 그 맞추는 일이 이 방식의 내용 전부입니다.
사용 절차
여섯 단계로 자리를 잡습니다.
- 역할을 정합니다. 쓰기를 받는 서버 하나와 읽기를 받는 사본 여럿으로 나눕니다. 관계형 데이터베이스는 대개 이 구조를 기본으로 지원합니다. 쓰기를 여러 대가 함께 받으면 같은 줄을 동시에 고치는 경우를 정리할 방법이 필요하므로, 대부분은 쓰기를 한 곳으로 모으는 구조에서 시작합니다.
- 전달 방식을 고릅니다. 사본이 받았다고 답할 때까지 기다린 뒤에 저장을 완료로 처리하는 방식과, 원본에 적고 바로 완료로 답한 다음 사본에는 뒤이어 보내는 방식이 있습니다. 앞쪽은 원본이 갑자기 죽어도 유실이 없지만 저장이 사본의 응답 시간만큼 느려집니다. 뒤쪽은 빠르지만 사본이 몇백 밀리초에서 몇 초까지 뒤처집니다.
- 처음 한 번 통째로 복사합니다. 원본의 현재 상태를 사본에 옮기고, 복사를 시작한 시점 이후의 변경 기록을 이어 붙여 따라잡게 합니다. 데이터가 크면 이 단계에만 몇 시간이 걸립니다.
- 읽기를 나눕니다. 코드에서 읽기용 연결과 쓰기용 연결을 따로 둡니다. 여기서 한 가지를 가려야 합니다. 방금 저장한 것을 바로 보여 주는 화면은 사본이 아니라 원본에서 읽습니다. 저장 직후에 사본에서 읽으면 방금 쓴 문서가 목록에 없는 화면이 나옵니다.
- 지연을 감시합니다. 사본이 원본보다 몇 초 뒤처져 있는지를 계속 재고, 그 값이 기준을 넘으면 알림을 받습니다. 지연이 벌어지는 동안에는 사본에서 읽는 화면이 오래된 값을 보여 주고 있다는 뜻입니다.
- 원본이 죽었을 때의 절차를 미리 적어 둡니다. 어느 사본을 원본으로 올릴지, 그 판단을 자동으로 할지 사람이 할지, 올린 뒤 나머지 사본은 새 원본을 따라가게 어떻게 바꿀지입니다. 이 문서가 없으면 장애가 난 날 밤에 그 결정을 처음 하게 됩니다.
적합한 상황과 한계
맞는 자리가 셋입니다. 읽기가 쓰기보다 훨씬 많은 서비스, 한 대가 멈춰도 서비스를 이어 가야 하는 경우, 그리고 무거운 분석 질의를 돌려야 할 때입니다. 세 번째는 자주 쓰입니다. 지난 분기 사용량을 집계하는 질의는 몇 분씩 걸리므로 사본에서 돌리면 고객이 쓰는 화면이 느려지지 않습니다.
안 맞는 자리도 분명합니다.
- 쓰기가 병목일 때 — 사본을 열 대로 늘려도 쓰기를 받는 곳은 여전히 한 곳입니다. 쓰기를 나눠야 한다면 데이터를 조각내 여러 서버에 담는 샤딩 쪽입니다.
- 데이터 양 자체가 한 대에 들어가지 않을 때 — 복제는 같은 것을 여러 벌 두는 방식이라 담을 수 있는 총량이 늘지 않습니다.
- 방금 쓴 값을 즉시 읽어야 하는 화면이 대부분일 때 — 읽기를 거의 다 원본으로 보내게 되어 사본이 놀게 됩니다.
한계는 셋입니다. 첫째, 지연이 사용자에게 보입니다. 저장한 문서가 목록에 몇 초 늦게 나타나는 화면은 사용자에게 버그로 읽히므로, 어느 화면이 사본을 읽는지 미리 정해 두어야 합니다. 둘째, 원본의 부담이 줄지 않습니다. 쓰기를 그대로 받으면서 변경 기록을 사본마다 보내는 일이 더해집니다. 사본을 계속 늘리면 어느 지점부터는 지연이 함께 늘어납니다. 셋째, 전부 성공하거나 전부 취소되어야 하는 트랜잭션의 경계가 원본에서만 온전합니다. 사본은 그 결과를 뒤따라 받으므로 진행 중인 상태를 읽을 수 있습니다.
실무 용례
"조회는 사본으로 돌리죠. 원본이 월요일 아침마다 밀립니다."
읽기 부하를 사본으로 옮기자는 제안입니다.
"저장 직후 화면은 원본에서 읽어야 합니다. 지연 때문에 안 보여요."
방금 쓴 값을 사본에서 읽으면 안 된다는 지적입니다.
"복제는 백업이 아닙니다. 지운 것도 같이 지워집니다."
두 장치의 역할이 다르다는 점을 바로잡는 말입니다.
페이지덱에서는 태오가 사본 두 대를 두고 조회를 그쪽으로 보냅니다. 화면마다 원본과 사본 중 어디서 읽는지를 목록으로 적어 두는데, 새 화면을 만들 때 이 목록을 먼저 보게 하면 판단이 개발자마다 갈리지 않습니다. 지연 값은 대시보드에 올려 두고 3초를 넘으면 알림이 갑니다.
원본을 사본으로 바꾸는 절차는 분기마다 한 번 실제로 해 봅니다. 해 본 적이 없으면 장애가 난 날에 그 문서가 맞는지부터 확인하게 됩니다.
흔한 오해
복제를 백업으로 여기는 경우가 가장 많습니다. 같은 데이터가 여러 대에 있으니 안전해 보입니다. 하지만 복제가 옮기는 것은 변경 그 자체입니다. 실수로 표 하나를 지우면 그 삭제가 사본에도 몇 초 안에 그대로 전달됩니다. 사람 실수와 잘못된 배포로 데이터가 망가지는 사고는 복제로 막지 못합니다. 그 사고에 대비하는 것은 특정 시점으로 되돌릴 수 있는 백업이고, 둘은 서로를 대신하지 않습니다.
사본을 늘리면 전체가 빨라진다고 보는 것도 흔합니다. 읽기는 실제로 나뉘지만 쓰기는 한 곳에 그대로 남고, 사본이 늘어날수록 원본이 변경 기록을 보내는 일이 늘어납니다. 어느 지점부터는 사본을 더해도 읽기만 조금 나아지고 지연은 나빠집니다. 읽기가 아니라 쓰기가 막혀 있다면 사본 수를 늘리는 대신 구조를 다시 봐야 합니다.
자주 헷갈리는 용어
| 용어 | 무엇을 나누는가 | 복제와의 차이 |
|---|---|---|
| 샤딩 | 데이터를 조각내 서버마다 다른 부분을 담는다 | 총량과 쓰기를 나눕니다. 복제는 같은 것을 여러 벌 두어 읽기와 장애를 나눕니다 |
같이 보면 좋은 페이지
마지막 업데이트 2026-09-16