Skip to content

트러블슈팅‐오프라인 사용과 데이터 동기화

minwooch edited this page Dec 4, 2024 · 1 revision

기본적으로 오프라인 상태에서 앱 사용이 가능하며, 동기화를 하고 나면 클라이언트의 꿈일기 내역과 서버의 꿈일기 내역이 서로 일치하게 되는 기능입니다.

전략

기본적으로 깃과 유사한 방법을 이용하는 것으로 결정했습니다. 꿈일기는 수정이 있을 때마다 새로운 버전을 가지며 해당 버전은 UUID로 생성합니다.
하지만 각 버전마다 어떤 내용을 가지고 있었는지 모두 저장하지는 않습니다.
또 클라이언트는 로컬 버전동기화 된 버전(마지막으로 동기화가 성공한 버전) 두 개의 버전 정보를 가지고 있으며, 서버는 모든 버전 리스트를 가지고 있습니다. 이 버전 정보들을 토대로 동기화를 진행합니다.

버전 체크 과정

이 과정은 클라이언트의 로컬 버전과 서버의 마지막 버전을 비교해서, 클라이언트에는 없고 서버에만 있는 꿈일기가 존재하는지 확인하는 과정이며, 꿈일기 내용을 주고받지는 않습니다.
깃으로 생각하자면 일종의 fetch all 과정이며 서버에 새로운 꿈일기가 있는 경우 image 이런 느낌입니다.

버전 체크 (1)
위와 같이 클라이언트와 서버의 꿈일기가 있습니다. 각 꿈일기의 상태는 다음과 같습니다.
꿈일기 A는 모종의 이유로 서버가 a1 이후 업데이트 된 a2 버전의 꿈일기를 가지고 있습니다.
꿈일기 B는 서버에만 존재합니다.
꿈일기 C는 로컬 버전과 서버의 마지막 버전이 c2로 일치합니다.
반대로 꿈일기 N은 해당 클라이언트에서 새롭게 작성한 일기로, 서버에 존재하지 않습니다.

버전 체크 (2)
클라이언트는 모든 꿈일기의 로컬 버전을 리스트로 서버에게 전달합니다.

버전 체크 (3)
꿈일기 C와 N은 서버에만 있는 꿈일기가 아닙니다. 따라서 이번 과정에서는 무시됩니다.
꿈일기 A는 클라이언트가 가지고 있는 a1 버전보다 더 최신 버전인 a2를 가지고 있습니다. 따라서 클라이언트는 서버로부터 꿈일기를 받아 올 필요가 있습니다.
꿈일기 B도 마찬가지입니다. 가장 최신 버전의 b3 버전의 데이터를 서버로부터 받아 올 필요가 있습니다.

버전 체크 (4)
그러므로 서버는 [A, B]로 응답합니다.

버전 체크 (5)
클라이언트는 각 꿈일기 A와 B의 동기화 필요true로 변경합니다. 여기서 꿈일기 B는 사용자에게 보이지 않는 임시 꿈일기입니다.

이렇게 버전 체크 과정이 끝납니다.

데이터를 주고 받는 과정

앞선 과정을 통해 동기화 필요true가 된 각 꿈일기의 데이터를 주고 받아서, 실제로 데이터 동기화가 일어나는 과정입니다.

클라이언트는 각 꿈일기의 content로컬 버전동기화 된 버전을 서버에게 전달합니다.
서버는 충돌 여부 등을 판단하고 클라이언트에게 content동기화 된 버전을 돌려줍니다.

서버에 새로운 버전이 있는 경우

1
앞의 버전 체크 과정이 끝난 상태에서 계속 진행합니다.

1 (1)
꿈일기 A의 로컬 버전동기화 된 버전을 서버에 전달합니다. 모두 a1 버전입니다.

1 (2)
꿈일기 A의 로컬 버전a1은 이미 서버의 버전 리스트에 존재합니다. 즉 꿈일기 A는 마지막으로 동기화 된 이후 어떤 변화도 없으며 오직 서버에서만 변화가 있었음을 의미합니다. 그러므로 서버는 최신 버전인 a2와 서버의 content를 돌려줍니다.

1 (3)
클라이언트는 로컬 버전동기화 된 버전a2로 업데이트 하고, 서버의 content로 변경한 후 동기화 필요를 false로 변경합니다.

서버에 새로운 꿈일기가 있는 경우

1 (1)
꿈일기 B는 임시 꿈일기이며, 꿈일기 A와 똑같이 버전 정보 null을 전송합니다.

1 (2)
서버는 버전 정보를 보고 임시 꿈일기임을 압니다. 그러므로 최신 버전인 b3과 서버의 content를 돌려줍니다.

서버에 존재하지 않는 일기인 경우

1 (1)
꿈일기 N은 로컬에서 새롭게 생성된 꿈일기입니다.

2
해당 꿈일기의 ID인 N은 서버에 없는 것이므로 단순히 서버에 N을 추가하고 성공했음을 알려줍니다.
모든 꿈일기들은 서버에서 알려주는 content동기화 된 버전을 업데이트 하고, 동기화 필요false로 변경합니다.

클라이언트에서 꿈일기 수정

1
클라이언트에서 꿈일기 N을 수정한 경우 위와 같이 현재 버전n2로 또 동기화 필요true로 변경됩니다.

동기화된 버전이 서버의 최신 버전과 일치합니다. 즉 깃을 생각하면 다음과 같은 느낌입니다.
업데이트 (1)

2
그러므로 서버는 클라이언트가 전송한 content로 업데이트하고 버전 리스트에 n2를 추가한 후 성공했음을 알려줍니다.

3
클라이언트는 동기화 된 버전n2로 업데이트 합니다.

다음과 같이 되는 것입니다.
업데이트 (2)

충돌

같은 계정으로 로그인 한 두 개의 클라이언트가 있을 때, 한 일기를 두 클라이언트가 동시에 수정한 경우 충돌이 일어나게 됩니다.

image
꿈일기 N을 각 클라이언트 로컬1로컬2가 각각 수정한 상황입니다.

어느 한 쪽은 "클라이언트에서 꿈일기 수정" 과정을 통해 먼저 동기화가 됩니다.
image
위 이미지는 로컬1이 먼저 동기화가 된 상황입니다.

다음은 로컬2가 동기화를 시도합니다. 로컬 2에서 꿈일기 N은 동기화 된 버전n2이고 현재 버전은 n4입니다. 서버는 [n1, n2, n3]를 가지고 있습니다. 동기화 된 버전n2가 서버의 최신 버전인 n3과 일치하지 않으므로 서버는 충돌임을 알 수 있습니다.
이제 서버는 정책에 따라 이 충돌을 해결합니다. 저희 팀은 간단하게 현재 서버의 content와 클라이언트가 전송한 content를 concat 하는 방식을 선택했습니다. 즉 단순히 두 content를 이어 붙이는 것입니다.

image
서버는 이렇게 이어 붙인 새로운 일기를, 새로운 버전인 n5로 이름 붙이고 이를 로컬2에게 n5라는 버전과 함께 돌려줍니다.

Clone this wiki locally