본문 바로가기

분산 시스템에서 ‘일관성’이란 무엇인가: 동시에 업데이트할 때 데이터가 어긋나는 이유

📑 목차

    동시에 저장했는데 화면이 갈라지는 순간을 먼저 떠올려야 한다

    분산 시스템에서 일관성 문제는 동시에 업데이트가 발생했을 때 데이터가 어디서, 어떤 순서로 보이는지부터 정리해야 풀린다.

    예를 들어 같은 주문의 상태를 두 개 서비스가 거의 동시에 바꾸는데, 한 화면은 "결제 완료"로 보이고 다른 화면은 "결제 대기"로 보이는 경우가 있다.

    이때 개발자는 "DB에 저장은 됐는데 화면이 왜 달라졌지"라고 느끼고, 운영자는 "방금 처리한 작업이 반영되지 않는다"라는 문의를 받는다.

    자주 생기는 오해는 "일관성은 데이터가 같다는 뜻"으로만 받아들이는 것이다.

    현실의 분산 환경에서는 데이터가 최종적으로 같아지는지, 즉시 같아지는지, 읽기마다 같아야 하는지 같은 약속이 먼저 다르다.

    일관성의 두 축을 구분하면 원인이 좁혀진다

    핵심 개념 1) 강한 일관성(Strong Consistency)

    정의: 한 번 성공한 쓰기(write)가 있으면, 그 이후의 읽기(read)는 어디서 읽더라도 그 쓰기를 반영한 값만 반환하도록 보장하는 모델이다.

    핵심 특징: "방금 저장한 값이 바로 보인다"라는 기대를 충족시키기 쉽고, 동시 업데이트에서도 결과가 한 줄로 정렬된 것처럼 관찰된다.

    주의점: 지연 시간과 가용성 비용이 커질 수 있으며, 네트워크 분리나 장애 상황에서 쓰기/읽기를 막아야 보장이 유지되는 경우가 있다.

    핵심 개념 2) 최종 일관성(Eventual Consistency)

    정의: 모든 업데이트가 전파되면 결국 같은 값으로 수렴하지만, 전파 중에는 읽기 위치에 따라 서로 다른 값이 관찰될 수 있는 모델이다.

    핵심 특징: 복제(replication)와 캐시를 적극 활용해 성능과 가용성을 높이기 쉬우며, 지역 분산이나 대규모 트래픽에서 유리하다.

    주의점: 동시 업데이트에서 충돌(conflict) 해결 규칙이 없으면 값이 흔들리거나, 사용자가 "저장했는데 안 보인다"라는 체감을 자주 겪는다.

    강한 일관성과 최종 일관성의 관찰 차이
    강한 일관성과 최종 일관성의 관찰 차이

    선택 기준을 표로 고정하면 설계 논쟁이 줄어든다

    항목 강한 일관성 최종 일관성
    동시 업데이트에서 관찰 읽기마다 같은 결과를 보이도록 만들기 쉽다 전파 지연 동안 서로 다른 값이 보일 수 있다
    사용자 체감 저장 직후 화면 반영 기대에 잘 맞는다 짧은 시간의 불일치에 대한 UX 설계가 필요하다
    운영 비용 지연 시간, 장애 시 처리 제한 등 비용이 커질 수 있다 충돌 해결, 재시도, 보정 작업 등 비용이 추가된다
    대표 위험 가용성 저하, 쓰기 차단으로 처리량이 떨어진다 중복 처리, 덮어쓰기(LWW)로 데이터 손실이 난다

    이 비교표의 목적은 "어느 쪽이 더 낫다"가 아니라, 어떤 화면/업무 흐름에서 어떤 약속이 필요한지 합의하는 데 있다.

    동시에 업데이트하는 구간이 있는 시스템은, 최소한 "어긋남을 허용하는 구간"과 "허용하면 안 되는 구간"을 분리해 적어야 한다.

    YES/NO 체크리스트로 '어긋남이 설계 문제인지' 가른다

    • YES: 같은 데이터가 캐시, 리더 DB, 팔로워 DB 등 여러 경로에서 읽힌다
    • YES: 같은 키에 대해 동시에 쓰기가 들어올 수 있으며, 순서 보장 규칙이 없다
    • YES: 업데이트 직후 읽기에서 값이 흔들리거나, 화면마다 다른 값을 보여 준 기록이 있다
    • NO: 모든 쓰기와 읽기가 단일 노드 또는 단일 리더로만 흐르도록 제한되어 있다
    • NO: 쓰기 충돌 시 버전 체크(조건부 업데이트)가 기본으로 걸려 있다
    • NO: 복제 지연과 캐시 갱신 지연이 사용자 흐름에 영향 없는 수준으로 통제되어 있다

    이 체크리스트에서 YES가 반복되면, "데이터가 어긋나는 이유"는 개별 버그보다 읽기/쓰기 경로의 혼합에서 나오는 경우가 많다.

    확인 순서를 고정하면 원인 후보가 빠르게 좁혀진다

    동시 업데이트로 데이터가 어긋날 때는 감으로 추측하기보다, 경로를 따라가며 증거를 모아야 한다.

    아래 절차는 강한 일관성/최종 일관성 어느 쪽이든 공통으로 적용되며, 무엇이 약속을 깨는지 찾는 데 초점이 있다.

    1. 경로: 모니터링 대시보드 → 서비스 지표 → "업데이트 직후" 구간 확대
    2. 체크 포인트: p95 지연 시간, 5xx, 재시도율이 같은 시점에 튀는지 확인한다.
    3. 경로: 로그 검색(예: Kibana Discover) → index 선택 → 동일 키로 필터
    4. 체크 포인트: 같은 데이터 키에 대해 서로 다른 요청이 거의 같은 시간에 쓰기를 수행했는지 본다.
    5. 경로: 데이터 저장소 콘솔/대시보드 → 복제 지연(Replication lag) 또는 리드 라우팅 설정 확인
    6. 체크 포인트: 읽기가 리더가 아니라 팔로워/리플리카로 흘러가며, 지연이 누적되는지 확인한다.
    7. 경로: 애플리케이션 설정 → 캐시 정책/TTL/무효화 규칙 확인
    8. 체크 포인트: 쓰기 후 캐시 무효화가 누락되거나, TTL 때문에 오래된 값이 계속 노출되는지 본다.
    9. 경로: DB 트랜잭션/동시성 제어 설정 → 격리 수준, 조건부 업데이트(버전/ETag) 사용 여부 확인
    10. 체크 포인트: 동시 쓰기에서 "마지막 쓰기가 덮어쓴다" 같은 규칙이 사실상 데이터 손실을 만들고 있는지 확인한다.

    동시 업데이트 불일치 점검 흐름도
    동시 업데이트 불일치 점검의 단계별 흐름

    실전 예시: 같은 키의 두 업데이트가 '서로를 지운' 경우

    문제: 프로필 수정 요청이 두 번 연달아 들어온 뒤, 한 필드가 원래 값으로 되돌아가는 현상이 발생했다.

    왜 발생: 두 요청이 서로의 변경을 모르는 상태에서 전체 레코드를 덮어쓰는 방식으로 저장했고, 충돌 감지 없이 마지막 쓰기가 승리했다.

    어떤 선택이 적합: 부분 업데이트와 조건부 업데이트를 결합해, 기준 버전이 다르면 저장을 거절하고 재시도 경로로 보내는 방식이 맞다.

    잘못 쓰면 어떤 문제: 무조건 재시도만 걸면 같은 충돌이 반복되어 지연이 커지고, 사용자 입장에서는 저장이 실패로 느껴질 수 있다.

    확인/해결: 동일 키의 업데이트 시점과 버전 값을 로그에서 확인하고, 버전 불일치가 나면 409 같은 충돌로 분기되도록 설계를 바꾼다.

    [로그 조각 예]
    key=user:18402
    write_a version=17 at 12:03:11.042
    write_b version=17 at 12:03:11.058
    result=lost_update
    detected=false

    이 예시에서 핵심은 두 요청이 같은 기준 버전에서 시작했다는 점이다.

    동시 업데이트를 피할 수 없다면, "누가 누구를 덮어쓰는지"를 탐지하고 처리하는 장치가 일관성 설계의 일부가 된다.

    재발 방지 포인트 3가지

    • 읽기 경로를 분리한다: "저장 직후 화면"은 리더/동기 경로로 강하게 보장하고, 목록/통계는 최종 일관성 경로로 허용 범위를 둔다
    • 충돌을 드러낸다: 버전/ETag 등 조건부 업데이트로 충돌을 숨기지 말고, 실패를 명시해 재시도나 병합으로 처리한다
    • 지연을 수치로 본다: 복제 지연과 캐시 갱신 지연을 대시보드에서 상시 관측해, 허용 범위를 넘기면 알람으로 올린다

    결론

    일관성은 "데이터가 결국 같아진다"가 아니라 "동시 업데이트가 있을 때 읽기가 어떤 규칙으로 보이게 할지"에 대한 약속이다.

    강한 일관성과 최종 일관성의 차이를 먼저 합의하면, 어긋남의 원인은 읽기/쓰기 경로 혼합과 충돌 처리 부재로 좁혀지는 경우가 많다.

    확인 순서를 고정하고 증거(로그·지연·충돌)를 모으면, 개별 버그처럼 보이던 문제가 설계 선택의 결과였는지 판단할 수 있다.

    연계 주제 제안: 조건부 업데이트(버전/ETag)로 동시성 충돌 줄이기, 복제 지연이 UX에 미치는 영향과 화면 설계가 다음 단계로 이어지기 좋다.

    FAQ

    Q1. 강한 일관성을 쓰면 동시 업데이트 문제가 완전히 사라지나

    읽기 결과가 흔들리는 문제는 줄어들 수 있다.

    다만 동시 업데이트 자체는 계속 발생하므로, 충돌을 어떻게 처리할지(거절, 재시도, 병합)는 여전히 설계가 필요하다.

    Q2. 최종 일관성을 쓰면 데이터가 틀린 상태로 영원히 남을 수도 있나

    전파와 수렴 규칙이 정상이라면 결국 같은 값으로 모인다.

    하지만 충돌 해결 규칙이 잘못되면 덮어쓰기나 데이터 손실이 생겨, 결과적으로 "틀린 값으로 수렴"할 수 있다.

    Q3. 동시 업데이트가 많은 서비스에서 가장 먼저 점검할 지표는 무엇인가

    복제 지연, 캐시 hit/miss 변화, 재시도율을 먼저 본다.

    이 세 가지가 업데이트 직후 구간에서 함께 흔들리면, 일관성 약속과 실제 경로가 어긋났을 가능성이 크다.