MyStock - Dropbox DB 동기화 기준과 Setup UX

MyStock은 집과 회사처럼 여러 PC에서 같은 데이터를 사용하고 있었고, SQLite DB는 Dropbox를 통해 서로 오가고 있었다. Schema 7이라는 새 기준을 만든 순간부터 Local DB와 Remote DB가 서로 다른 상태로 존재할 가능성이 생겼다. 한 PC는 이미 새 구조를 사용하고 있는데 Dropbox에는 이전 Schema의 DB가 남아 있을 수도 있었고, 반대로 새로 실행한 PC의 Local DB는 오래됐지만 Remote에는 현재 구조의 DB가 올라가 있을 수도 있었다. 그래서 마지막 단계에서 먼저 정해야 했던 것은 Setup 화면이 아니었다. Local과 Remote 중 어느 DB를 언제 기준으로 삼을 것인지, 그리고 둘의 상태가 다를 때 프로그램이 어디까지 자동으로 판단해도 되는지를 다시 정해야 했다.

방향은 내가 정했고, ChatGPT와는 Local·Remote 조합별로 어떤 판단이 일관되어야 하는지 정리했다.

 

Codex는 그 기준이 실제 startup과 Dropbox 동기화 흐름에서 지켜지도록 구현하고 반복해서 검증했다.

Dropbox DB 동기화 기준

Dropbox를 사용한다고 해서 두 DB를 항상 같은 상태로 복제하는 단순한 미러 구조로 만들 수는 없었다. 파일은 같아 보여도 DB Schema가 다를 수 있고, 현재 실행 중인 MyStock이 이해할 수 없는 DB가 Remote에 존재할 수도 있기 때문이다. 그래서 기준을 파일의 수정 시간이나 단순히 더 큰 Schema 숫자에 두지 않았다. 가장 먼저 확인할 것은 현재 실행 중인 App이 이해할 수 있는 DB인가였다. App이 사용하는 현재 Schema를 기준으로 Local과 Remote를 각각 판단하고, 안전하게 자동 결정할 수 있는 경우에만 Pull이나 Push를 진행하는 쪽으로 정리했다.

 

Local DB가 오래됐지만 Remote DB가 현재 Schema라면 Remote를 가져오는 것이 자연스럽다. 반대로 Local은 현재 Schema인데 Remote가 오래됐다면 프로그램이 임의로 원격을 덮어쓰지 않고, 현재 Local DB로 Remote를 갱신할 것인지 사용자가 결정하도록 했다. Remote가 실행 중인 App보다 더 새로운 Schema라면 숫자가 더 크다는 이유로 가져오지 않고 동기화를 중단하는 쪽을 선택했다.

 

중요한 것은 “더 새로운 DB가 무조건 winner”라는 규칙을 만들지 않은 것이다. App과의 호환 여부가 먼저였고, 자동으로 판단하기 애매하거나 데이터 의미가 달라질 수 있는 상황에서는 파일을 바꾸기보다 멈추는 쪽을 우선했다.

Local·Remote DB Schema 판단

이 기준을 적용하면서 Local과 Remote의 역할도 분명해졌다. 프로그램을 시작할 때는 먼저 Remote 상태를 확인하고, 필요하면 검증된 DB를 가져와 이번 실행에서 사용할 Local DB를 확정한다. 한 번 실행이 시작된 뒤에는 Remote가 바뀌었다는 이유만으로 사용 중인 DB를 즉시 교체하지 않는다.

 

실행 중에는 Local DB가 작업의 기준이 되고, 변경된 내용을 안전하게 Remote에 반영한다. 즉 Dropbox는 두 파일을 실시간으로 맞추는 미러라기보다, startup에서 사용할 DB를 확정한 뒤 Local의 변경을 Remote와 안전하게 맞추는 동기화 장치에 가까워졌다. 기존 DB를 다루는 방식도 같은 원칙을 따랐다. 오래된 Local DB는 바로 삭제하지 않고 원본을 보존한 뒤 현재 구조에서 다시 시작할 수 있게 했고, Remote의 오래된 DB 역시 사용자의 결정 없이 자동으로 덮어쓰지 않았다.

Schema mismatch와 사용자 선택

Local과 Remote의 상태가 다르다고 해서 모든 경우를 사용자에게 물어볼 필요는 없었다. 안전하게 결정할 수 있는 경우에는 자동으로 진행하고, 실제로 어느 한쪽의 데이터를 변경해야 하는 순간에만 판단을 사용자에게 넘기는 편이 자연스러웠다. 대표적인 경우가 현재 Local DB는 Schema 7인데 Dropbox에는 Schema 5 DB가 남아 있는 상황이었다. 이때 MyStock은 Remote DB가 이전 Schema라는 사실을 보여주고, 현재 Local DB로 Dropbox를 업데이트할지 아니면 이번 실행에서는 동기화를 끌지 선택하게 한다.

이 화면은 단순한 경고창이라기보다 이번 동기화 정책의 핵심을 그대로 보여준다. 프로그램이 “Local이 더 최신이니 알아서 덮어쓴다”라고 결정하지 않고, 원격 데이터를 변경하는 순간에는 사용자가 그 의미를 확인할 수 있도록 한 것이다.

Startup Dropbox 동기화 가시성

정책을 정한 뒤에는 동기화가 실제로 진행되는 과정도 사용자에게 보여줄 필요가 있었다. DB가 없는 초기 실행이나 Remote DB를 가져오고 올리는 과정이 길어지면 프로그램이 멈춘 것처럼 보일 수 있었기 때문이다. 그래서 startup에서 Dropbox DB 다운로드나 업로드가 필요한 경우에는 foreground 진행 화면을 사용해 현재 무엇을 기다리고 있는지 확인할 수 있도록 했다.

평소 실행 중에는 상태 영역에서 Dropbox 상태를 확인할 수 있지만, 시작 단계에서 실제 DB 파일을 준비하는 작업만큼은 사용자가 완료 여부를 확인한 뒤 프로그램이 이어서 시작하도록 했다.

Configuration Setup과 Local Config

DB 동기화 기준이 정리되고 나서야 처음 시작했던 .env 제거 작업의 마지막 단계인 Setup UX를 붙일 수 있었다. 이제 Local Config가 없거나 필수 설정이 준비되지 않은 상태라면 예전 환경 변수나 숨겨진 기본값으로 넘어가지 않는다. 프로그램을 계속 사용하려면 설정이 필요하다는 사실을 먼저 보여주고, 환경 설정을 진행할지 종료할지 사용자가 선택한다.

환경 설정 화면에서는 계좌의 표시 이름과 실제 계좌번호, 계좌 종류를 각각 입력할 수 있고 같은 종류의 계좌도 추가할 수 있다. KIS App Key와 Secret, 공용 데이터에 사용할 계좌와 EIA API Key를 등록하고, 필요한 경우 KRX와 Dropbox 설정도 같은 화면에서 관리한다. Dropbox 역시 단순히 인증 정보만 입력하는 것이 아니라 동기화 사용 여부, 원격 DB 경로, 동기화 간격까지 현재 PC의 Local Config에서 결정하도록 했다.

이 설정은 SQLite DB와 분리되어 있다. 계좌의 현재 표시 이름과 종류, API 인증 정보처럼 지금 이 PC에서 사용하는 값은 Local Config가 책임지고, 실제 투자 데이터는 SQLite DB가 담당한다. Dropbox는 설정 파일을 공유하는 것이 아니라 그 SQLite DB를 여러 PC 사이에서 안전하게 연결하는 역할만 맡는다.

 

설정을 저장한 뒤에는 프로그램을 다시 실행할 필요 없이 그대로 startup을 이어가도록 했다. 사용자는 더 이상 .env 파일을 직접 만들거나 고정된 계좌 슬롯 이름을 코드의 규칙에 맞춰 작성할 필요가 없다.

Dashboard에서 확인한 최종 상태

최종 실행 화면에서는 앞에서 정한 기준이 실제 사용 형태로 연결된다. 계좌 그룹에는 Local Config에서 정한 표시 이름이 나타나고, CMA는 일반 투자 포트폴리오와 분리되면서 전체 자산을 위한 잔액 정보는 별도로 유지된다. 하단 상태 영역에서는 DB 업데이트 진행 상황과 Dropbox 상태를 함께 확인할 수 있다. startup에서 DB를 확정하고 나면 평소에는 사용자가 동기화 세부 구현을 의식하지 않아도 되지만, 현재 변경 여부나 작업 상태는 필요한 만큼 드러나도록 했다.

처음 시작은 .env를 없애는 일이었다. 그 작업을 따라가다 보니 하드코딩된 계좌 구조가 드러났고, 계좌 Identity와 DB의 책임을 다시 나눠야 했다. 그리고 DB 구조가 바뀌자 마지막에는 여러 PC에서 어떤 DB를 기준으로 사용할 것인지까지 다시 정해야 했다.

 

결국 역할은 명확하게 나뉘었다. Local Config는 지금 이 PC에서 사용할 계좌와 인증 정보를 관리하고, SQLite DB는 실제 데이터를 보존한다. Dropbox는 현재 App이 이해할 수 있는 DB인지 확인한 뒤 Local과 Remote를 연결하고, 자동으로 판단하기 어려운 상태에서는 데이터를 바꾸기보다 멈추거나 사용자에게 선택을 넘긴다.

 

Setup UX는 그 구조를 사용자가 직접 설정 파일을 편집하지 않고 사용할 수 있게 만든 마지막 단계였다. env 파일에서 발견한 문제로 시작한 작업은 DB 구조와 동기화 기준, 실제 startup과 설정 화면까지 연결하고 나서야 마무리됐다.