소켓 응용 3/5 · SYNC

두 화면이 달라졌다면
무엇이 정답일까요?

실시간 이벤트만 전달하면 잠시 끊긴 화면은 뒤처집니다. 서버의 기준 상태, 버전 번호와 스냅숏으로 다시 맞추는 과정을 실험합니다.

이 편의 핵심 질문놓친 이벤트가 있을 때 어떻게 같은 상태로 돌아올까?서버 버전을 비교하고
스냅숏으로 맞추기

나쁜 결과와 안전한 결과를 비교하세요

연결이 끊긴 두 상태판을 다시 맞춥니다

보는 순서이벤트만 선택B 끊기버전 비교

  1. 1같은 시작
  2. 2끊김
  3. 3변경
  4. 4불일치
실험 시작을 누르면 첫 장면부터 움직입니다모두 v1
사용자 AONLINE20°마지막 버전 v1
기준 서버SOURCE20°현재 버전 v1
사용자 BONLINE20°마지막 버전 v1

LIVE EVENTS ONLY세 화면이 같은 상태입니다 ✓

이벤트만 전송 시나리오입니다. 실험 시작을 눌러 네 장면을 따라가세요.

시작 전

화면에서 코드로 옮길 때

이 편의 원리 세 가지

01이벤트와 상태를 구분합니다.

이벤트는 무엇이 바뀌었는지, 상태는 지금 정답이 무엇인지 말합니다.

02서버가 기준 버전을 갖습니다.

각 화면은 마지막으로 적용한 서버 버전을 기억합니다.

03차이가 크면 스냅숏을 받습니다.

누락 이벤트를 모두 재생하기 어렵다면 현재 상태로 한 번에 맞춥니다.

구현 체크리스트

최소 네 조각으로 시작하세요.

데모의 시각 요소를 실제 프로토콜 필드와 런타임 동작으로 옮기면 됩니다.

  1. 1서버 기준 상태클라이언트 표시값과 구분되는 권위 있는 값
  2. 2증가 버전변경 순서를 비교할 수 있는 revision 또는 offset
  3. 3재연결 handshake클라이언트의 마지막 적용 버전을 전달
  4. 4스냅숏 + 이후 이벤트기준 시점이 맞는 두 데이터를 원자적으로 연결
이 데모는 네트워크 동작을 단계별로 보여주는 개념 시뮬레이션입니다.

공동 편집처럼 동시에 같은 값을 바꾸는 문제는 별도 충돌 정책이 필요합니다. 이 편은 연결 누락 뒤 상태 복구에 집중합니다.

이 데모에 대하여

끊겼다 돌아온 화면을 다시 맞추는 두 방법

화면에는 서버의 기준값과 두 개의 클라이언트 화면이 각각 버전 번호와 함께 표시됩니다. 한쪽 화면을 잠시 끊었다가 다시 붙이면 그동안의 변경을 놓치는데, 그 상태에서 무엇을 해야 다시 같은 값으로 돌아오는지를 두 설계로 비교합니다. 세 개의 값과 세 개의 버전을 한 화면에 나란히 둔 것이 이 데모의 전부이고, 숫자가 어긋나는 순간이 문제의 정의입니다.

  1. 이벤트만 보내는 설계를 고르고 값이 몇 번 바뀌는지 봅니다.
  2. 오른쪽 화면을 끊고 그동안 서버 값을 바꿉니다.
  3. 다시 연결한 뒤 두 화면의 값이 다른지 확인합니다.
  4. 각 화면에 붙은 버전 번호를 서버 버전과 비교합니다.
  5. 다른 설계로 바꿔 같은 순서를 반복합니다.
  6. 재연결 시점에 스냅숏이 오가는 단계를 확인합니다.
  7. 스냅숏을 받은 뒤 버전 번호가 서버와 같아지는지 봅니다.
  8. 두 설계에서 최종 화면 값이 일치하는지 정리합니다.
  9. 끊긴 화면이 그동안 어떤 값을 보여주고 있었는지 확인합니다.
  10. 서버 버전이 얼마나 앞서 있었는지 숫자로 세어 봅니다.
  11. 왼쪽 화면은 끝까지 서버와 같은 버전을 유지하는지 봅니다.

값이 어긋나고 다시 맞는 과정

01

이벤트는 놓치면 복구되지 않습니다.

무엇이 바뀌었는지만 보내는 방식은 그 순간에 듣고 있어야 성립합니다. 끊긴 동안 지나간 변경은 다시 오지 않으므로 화면은 옛 값에 머뭅니다. 그런데 연결은 다시 붙었기 때문에 화면상으로는 정상으로 보이고, 값이 틀렸다는 사실을 사용자도 프로그램도 모릅니다. 이 조용한 어긋남이 가장 다루기 어려운 종류의 문제입니다.

02

버전 번호가 어긋남을 드러냅니다.

각 화면이 마지막으로 반영한 버전을 기억하고 있으면, 서버 버전과 비교해 뒤처졌는지 바로 알 수 있습니다. 값 자체를 비교하는 방식은 우연히 같은 값이면 구분되지 않지만 버전은 항상 앞으로만 가므로 확실합니다. 화면에서 버전을 값 옆에 항상 붙여 표시하는 이유가 이것입니다.

03

서버가 기준을 갖습니다.

여러 화면이 서로를 보고 맞추려 하면 어느 쪽이 맞는지 정할 수 없습니다. 그래서 서버의 값을 기준으로 두고 화면은 그것을 따라가는 구조로 만듭니다. 화면 세 개 중 서버 칸을 시각적으로 구분해 둔 것은 이 셋이 대등하지 않다는 점을 보이기 위해서입니다.

04

차이가 크면 통째로 받는 편이 낫습니다.

놓친 변경이 몇 개뿐이면 그것만 다시 보내면 되지만, 오래 끊겨 있었다면 그 목록이 길어집니다. 그때는 지금 상태를 통째로 한 번 보내는 쪽이 간단하고 확실합니다. 두 방법 중 무엇을 쓸지는 뒤처진 정도로 정하며, 화면은 스냅숏을 받는 쪽을 보여줍니다.

05

기준 시점이 맞아야 합니다.

지금 상태를 받는 동안에도 서버 값은 계속 바뀔 수 있습니다. 스냅숏을 받은 시점과 그 이후 이벤트를 듣기 시작한 시점 사이에 빈틈이 있으면 다시 어긋납니다. 그래서 스냅숏에는 그것이 어느 버전의 상태인지가 함께 붙어야 하고, 화면에서 스냅숏 이후 버전이 정확히 서버와 같아지는 것이 그 표현입니다.

06

끊김을 상태로 표시합니다.

오른쪽 화면의 연결 여부를 별도 값으로 들고 있습니다. 끊긴 동안에도 그 화면은 마지막 값을 그대로 보여주기 때문에, 화면만 봐서는 멀쩡해 보인다는 점을 재현하려면 연결 상태와 표시 값을 분리해야 했습니다.

07

동시 수정은 다루지 않습니다.

이 화면이 다루는 것은 놓친 변경을 따라잡는 문제이지 두 사람이 같은 값을 동시에 바꿨을 때 누구를 따를지 정하는 문제가 아닙니다. 후자는 별도의 규칙이 필요하고 훨씬 복잡합니다. 비교 대상을 하나로 좁히려고 서버 값만 바뀌도록 구성했습니다.

08

재연결은 성공의 시작일 뿐입니다.

연결이 다시 붙었다는 것과 화면이 맞다는 것은 다른 이야기입니다. 많은 구현이 재연결까지만 처리하고 그 뒤의 상태 복구를 빠뜨리는데, 그러면 사용자는 연결 표시가 정상인 화면에서 틀린 값을 보게 됩니다. 재연결 시점에 무엇을 주고받을지가 실시간 화면 설계에서 가장 자주 빠지는 부분입니다.

09

짧은 끊김이 더 위험합니다.

오래 끊기면 사용자도 알아채고 새로 고치지만, 몇 초짜리 끊김은 아무도 모르게 지나갑니다. 그런데 그 몇 초 사이에 값이 바뀌었다면 화면은 그때부터 계속 틀린 값을 보여줍니다. 화면에서 끊김 구간을 짧게 잡아 둔 것은 이 상황을 재현하기 위해서이고, 눈에 띄지 않는 사고가 더 오래 남는다는 점이 이 편의 요지입니다.

복구 구조만 보여줍니다.

브라우저는 어떤 서버와도 통신하지 않으며 값과 버전은 미리 정해 둔 시나리오를 따라 움직입니다. 실제 구현에서는 여기 없는 것들이 필요한데, 스냅숏을 만드는 비용과 그 크기, 얼마나 뒤처졌을 때 스냅숏으로 전환할지의 기준, 이벤트를 어디에 얼마나 보관할지, 클라이언트가 아주 오래 끊겼다가 돌아왔을 때의 처리, 그리고 여러 서버가 있을 때 버전 번호를 누가 발급할지가 모두 별도로 정해져야 합니다. 또한 이 화면은 값이 하나뿐이라 스냅숏이 작지만, 실제 화면은 목록과 중첩된 구조를 담고 있어서 전체를 다시 받는 비용이 훨씬 큽니다. 여러 사람이 같은 문서를 동시에 편집하는 경우는 이 화면의 방식으로 해결되지 않습니다. 그 경우에는 누구의 변경을 남길지 정하는 규칙이 먼저 필요하고, 그 규칙에 따라 화면을 맞추는 방식 자체가 달라집니다. 이 화면이 다루는 것은 정답이 서버에 하나만 있는 경우이고, 그 전제가 깨지는 순간 버전 번호 비교만으로는 부족해집니다. 화면의 값이 숫자 하나뿐인 것도 비교를 단순하게 유지하려는 선택이며, 실제 화면 상태는 훨씬 큰 구조라 어디까지가 한 번에 맞춰야 할 단위인지부터 정해야 합니다.

참고 자료RFC 6455 — WebSocket 프로토콜MDN — WebSocket API

실험을 마쳤다면