AI로 만든 앱에 실시간 협업 기능 넣기 (다른 사람의 작업을 망치지 않고)

두 사람이 동시에 앱을 편집하면 실시간 협업이 깨진다 — 한 사람의 변경 사항이 조용히 사라지거나, 덮어써지거나, 상대방이 보는 화면과 모순된다. 세 가지 실패 유형과 하나씩 적용하는 세 가지 해결책으로 문제를 해결할 수 있다.

두 사람이 동시에 같은 앱을 편집하면 어떻게 될까?

실시간 협업은 두 사람이 동시에 같은 앱 데이터를 편집할 때 서로의 작업을 덮어쓰지 않도록 막아주는 장치다 — 이를 건너뛰면 두 번째 사람의 저장이 첫 번째 사람의 작업을 조용히 지워버릴 수 있다. 한 팀에게 실제로 일어난 일을 살펴보자.

한 사용자가 팀과 함께 쓰는 할 일 목록을 만들었다. 금요일 오후, 팀원 두 명이 동시에 그 목록을 열었다. 둘 다 이렇게 보고 있었다:

  • 할 일 1: 장보기
  • 할 일 2: 엄마한테 전화하기
  • 할 일 3: 회의 일정 잡기

팀원 A는 “장보기”에 체크했다. 팀원 B는 “공유기 고치기”를 추가했다. 둘 다 저장 버튼을 눌렀다.

팀원 A가 화면을 새로고침하자 이렇게 보였다:

  • 할 일 1: 장보기 (완료)
  • 할 일 2: 엄마한테 전화하기
  • 할 일 3: 회의 일정 잡기

“공유기 고치기”는 사라져 있었다. 팀원 B의 작업이 없어진 것이다.

이것이 바로 충돌(collision)이다: 동시 쓰기가 일어나면 한 사람의 변경 사항이 사라진다. 마치 기능처럼 들리지만, 사실은 데이터 손실을 막는 수정 사항이다. 이 장치가 없으면 두 사람이 동시에 손을 대는 순간 앱이 망가진다.

실시간 협업에서 가장 흔한 버그는 무엇일까?

실시간 협업은 주로 세 가지 방식으로 깨진다: 쓰기 작업이 조용히 사라지거나, 화면에 오래된 데이터가 표시되거나, 두 사람이 서로 모순되는 사실을 보게 되는 경우다. 각각 다르게 나타나며, 각각 다른 해결책이 필요하다.

실패 유형 1: 사라진 쓰기 (조용한 데이터 손실)

두 사람이 동시에 저장한다. 두 번째 저장이 첫 번째 저장을 덮어쓴다. 두 번째 사람은 자신의 변경 사항이 반영된 것을 보지만, 첫 번째 사람은… 아무것도 보지 못한다. 혹은 새로고침을 하고서 자기 작업이 어디로 갔는지 어리둥절해한다.

실제 사례: 웨딩 플래너와 그녀의 어시스턴트가 하객 명단을 함께 작업하고 있었다. 어시스턴트가 참석 확답 세 건을 추가하는 동안, 플래너는 두 건을 “확정”으로 표시했다. 플래너의 표시가 사라졌다. 아무도 눈치채지 못하다가, 플래너가 후속 전화를 돌리면서 이미 참석하겠다고 답한 사람들에게 또 초대장을 보내는 이중 작업이 벌어지고 나서야 드러났다.

실제로 많은 앱들은 “저장” 버튼을 눌렀을 때뿐 아니라 키를 입력할 때마다 저장함으로써 이 문제를 해결한다. 구글 시트, 노션, 피그마 모두 그렇게 한다. 당신의 앱도 이런 동작이 필요하다.

실패 유형 2: 오래된 새로고침 (옛날 데이터 보기)

사용자 A가 할 일을 수정한다. 사용자 B는 그 페이지를 열어둔 채로 예전 버전을 보고 있다. B는 이 오래된 데이터를 기준으로 변경을 가한다. 이제 두 사람에게는 보이지 않는 충돌이 생긴 것이다.

실제 사례: 보험 손해사정사와 시공업자가 한 건의 보상 청구를 함께 처리하고 있었다. 사정사는 새로 받은 사진을 근거로 “예상 수리비: 3,000달러”를 “5,000달러”로 수정했다. 시공업자의 화면에는 여전히 3,000달러가 표시되어 있었다. 그는 3,000달러 기준으로 승인 양식을 제출했다. 이 충돌은 나중에야 발견됐다.

실시간 업데이트가 없으면 두 사람 모두 같은 버전을 보고 작업하고 있다고 _생각_한다. 하지만 실제로는 그렇지 않다.

실패 유형 3: 연쇄적 모순 (두 개의 진실)

한 사용자가 레코드를 삭제한다. 다른 사용자는 그 레코드의 상세 화면을 보고 있는 중이다. 한 사람은 “삭제됨”을 보고, 다른 사람은 여전히 전체 레코드를 보고 있다. 이제 두 사람은 서로 다른 사실을 기준으로 움직이게 된다.

실제 사례: 자원봉사 코디네이터가 한 근무 시간대를 “취소됨”으로 표시한다. 아직 새로고침하지 않은 자원봉사자에게는 여전히 “모집 중”으로 보인다. 그는 그 시간대의 봉사자를 모집하기 시작한다. 몇 시간 뒤, 애초에 존재하지도 않았던 근무 시간대에 두 사람이 나타난다.

실시간 협업 버그는 어떻게 고칠까?

순서대로, 하나씩 고쳐 나가면 된다: 점진적 저장으로 쓰기 충돌을 감지하고, 로컬에서 하던 편집을 잃지 않도록 새로고침을 병합하고, 충돌을 숨기지 말고 드러내는 것. 실시간 협업을 첫날부터 완벽하게 풀어낼 필요는 없다.

해결책 1: 쓰기 충돌 감지하기 (점진적 저장)

“저장” 버튼을 눌렀을 때뿐 아니라 모든 변경 사항이 즉시 저장되도록 만든다. 이것이 가장 중요한 해결책이다.

사용자가 필드를 수정하면 지금 바로 데이터베이스로 전송한다. 작은 “저장됨” 표시나, 동기화가 끝나면 사라지는 점 하나를 보여준다. 만약 두 번째 사람이 동시에 저장한다면, 데이터베이스 입장에서는 다음과 같이 보여야 한다:

  • 사용자 A의 변경 사항이 먼저 도착한다.
  • 사용자 B의 변경 사항이 나중에 도착한다.
  • 사용자 B가 이긴다 (마지막에 쓴 사람이 이기는 방식, last-write-wins).

가혹하지만 정직한 방식이다: 적어도 한 사람은 자기 변경 사항이 반영되지 않은 걸 보게 되고, 다시 시도할 수 있다.

빌더에게 요청할 것: “저장” 버튼이 아니라 키 입력마다, 혹은 사용자가 타이핑을 멈춘 지 2초 후에 저장이 실행되도록 한다. 동기화 표시를 보여준다. 테스트 방법: 브라우저 창 두 개에서 앱을 열고 같은 필드를 편집해본다. 한쪽의 변경 사항이 다른 쪽을 눈에 보이게 덮어써야 한다.

해결책 2: 로컬 편집을 잃지 않고 새로고침하기

데이터베이스를 5초마다 폴링하든(혹은 WebSocket으로 업데이트를 푸시하든), 사용자가 현재 하고 있는 편집을 짓밟지 않으면서 새 데이터를 병합해야 한다.

잘못된 방법: 페이지 전체를 다시 불러온다. 로컬 편집이 전부 사라진다.

올바른 방법: 사용자가 현재 편집하고 있지 않은 필드만 업데이트한다. 제목을 타이핑하고 있다면 건드리지 않는다. 마감일을 건드리고 있지 않다면 서버 값으로 업데이트한다.

빌더에게 요청할 것: 데이터베이스에서 새 데이터를 가져올 때는 병합한다: 로컬 편집은 유지하고 나머지는 업데이트한다. 실제 프레임워크에서는 대개 코드 두 줄이면 된다. 테스트 방법: 한 창에서 한 필드를, 다른 창에서 다른 필드를 동시에 편집해본다. 두 변경 사항 모두 살아남아야 한다.

해결책 3: 진실을 명확히 보여주기

충돌이나 오래된 데이터가 있을 때는 보여줘야 한다. 숨기지 말 것.

예시:

  • “이 할 일은 다른 사람이 삭제했습니다. 되돌릴까요?”
  • “타이핑하는 동안 누군가 이 목록에 항목 세 개를 추가했습니다. [새 항목 보기]”
  • “지금 보고 있는 화면은 2분 전 버전입니다. 최신 내용을 보려면 새로고침하세요.”

빌더에게 요청할 것: 로드할 때, 보여주고 있는 데이터에 타임스탬프가 있는지 확인한다. 30초 이상 지난 데이터인데 사용자가 편집을 시도하면 경고를 보여주고 다시 가져온다. 목록을 보여주고 있다면, 오류처럼 보이지 않고 사용자의 자연스러운 행동으로 느껴지는 “새로고침” 버튼을 둔다.

실시간 협업이 완전히 해결되면 어떤 모습일까?

최고 수준의 예시는 이렇다: 당신과 내가 함께 문서를 편집하고, 내가 타이핑하면 당신은 내 커서가 움직이는 걸 보고, 텍스트가 양쪽 화면에 즉시 나타나며 누구의 작업도 사라지지 않는다. 이를 위해서는 세 가지가 함께 맞물려야 한다:

  1. 모든 키 입력이 즉시 저장된다 — 버튼을 기다리지 않는다.
  2. 충돌은 규칙에 따라 해결된다 — 두 사람이 같은 단어를 동시에 편집하면, 시스템이 승자를 정한다(보통 마지막에 쓴 사람이 이기거나, 충돌 알림이 뜬다).
  3. 업데이트가 즉시 도착한다 — WebSocket, Server-Sent Events, 혹은 (Firebase처럼) 푸시를 지원하는 데이터베이스를 통해서다.

대부분의 앱은 첫날부터 이 정도까지는 필요 없다. 점진적 저장(해결책 1)부터 시작하라. 두 사람이 동시에 쓰기 시작하면 폴링 + 병합(해결책 2)을 추가하라. 충돌이 실제로 골칫거리가 될 때만 즉시 푸시를 추가하라.

출시 전에 실시간 협업을 어떻게 테스트할까?

출시 전에 브라우저 창 두 개로 세 가지 테스트를 실행하라: 동시 저장 테스트, 오래된 데이터 테스트, 새로고침 테스트. 각각 명확한 합격/불합격 기준이 있다.

테스트 1: 동시 저장 테스트

  • 브라우저 창 두 개에서 앱을 연다.
  • 창 1에서 필드 X를 편집하고 저장한다.
  • 창 2에서 필드 Y를 편집하고 바로 이어서 저장한다.
  • 두 창을 모두 새로고침한다.
  • 합격: 두 편집 사항이 모두 남아 있다. 불합격: 한쪽 편집이 사라졌다.

테스트 2: 오래된 데이터 테스트

  • 창 1에서 앱을 열고 아무것도 건드리지 않는다.
  • 창 2에서 큰 변화를 준다(행을 추가/삭제하거나 제목을 바꾼다).
  • 창 1로 돌아간다 (여전히 예전 데이터가 표시된 상태).
  • 창 1의 오래된 버전을 편집해본다.
  • 합격: 경고가 뜨거나 깔끔하게 병합된다. 불합격: 창 2의 변경 사항을 덮어쓴다.

테스트 3: 새로고침 테스트

  • 의미 있는 작업을 진행 중인 상태를 만든다(절반쯤 채운 양식, 임시 저장된 메시지).
  • 페이지를 새로고침한다.
  • 합격: 작업 내용이 그대로 남아 있다. 불합격: 사라졌다.

키 입력마다 저장해야 할까, 저장 버튼을 기다려야 할까?

키 입력마다 저장하라. 이 결정 하나만으로 실시간 협업의 80%를 완성할 수 있다 — 나머지는 그것을 눈에 보이게 만들고 충돌을 처리하는 일이다.

이제 사용자들은 당연히 이런 동작을 기대한다. 지메일, 구글 문서, 슬랙—현대적인 앱은 모두 이렇게 한다. 당신의 앱도 그래야 한다.

가장 먼저 해야 할 단 한 가지: 모든 변경 사항이 자동으로 저장되게 만든다. 작은 표시(“저장 중…” 후 사라짐)를 보여준다. 두 사람이 동시에 편집할 때 무슨 일이 일어나는지 지켜본다. 만약 한쪽의 변경 사항이 사라진다면, 그것이 다음 해결 과제다. 한 번에 하나씩 해결하는 편이, 첫날부터 완벽한 협업을 만들려는 시도보다 낫다.