퓨전보드 개발로그 · 4화
브라우저 탭을 퓨전보드 macOS 앱으로 바꿨다: 창보다 서버 소유권이 먼저였다
AI는 로컬 웹앱을 앱이라고 불렀다. 앱으로 만들고 이름은 퓨전보드로 하라고 했다. 첫 네이티브 래퍼는 남의 서버를 자기 것으로 착각하고, 보고서가 메인 화면을 덮었다. 독립 창보다 서버 소유권, 상태 확인, 저장, 종료라는 계약이 더 중요했다.
8월 15일 새벽 4시 19분에 물었다. 이거 앱으로 만들었지? 답은 “네, 실제로 실행되는 로컬 웹 앱으로 만들었습니다”였다. 1분 뒤 앱 열어 보라고 했더니, AI는 앱 안의 브라우저에 게시판을 띄우고 열었다고 했다. 2분 뒤에 다시 물었다. “그니까 웹 브라우져야? 앱으로는 안만들었어?” 그제야 독립 실행형 macOS 앱은 아직 만들지 않았다는 답이 돌아왔다.
개발자에게 앱과 나에게 앱
개발하는 쪽에서 보면 브라우저에서 도는 웹 애플리케이션도 앱이다. 내가 기대한 건 달랐다. Dock에 아이콘이 있고, 주소창 없는 독립된 창이 뜨고, 닫으면 정리되는 macOS 앱이다. 같은 단어가 서로 다른 실행 경험을 가리키고 있었다. 그래서 짧게 정했다. 앱으로 만들고, 이름은 퓨전보드라고 지어.
첫 래퍼의 다섯 가지 문제
AppKit으로 창을 만들고 그 안에 웹 화면(WKWebView)을 띄우는 래퍼를 만들었다. 겉보기엔 금방 앱이 됐다. 그런데 감사 에이전트가 초기 구현에서 문제를 줄줄이 찾았다.
- 이미 떠 있던 다른 개발 서버를 자기 서버로 착각하고 그냥 붙었다
- 서버 상태 확인이 늘 같은 값을 돌려줘서 실제 준비 상태를 알 수 없었다
- 데이터를 갱신하는 도중에 화면이 읽으면 반쯤 쓴 파일을 볼 수 있었다
- 앱을 닫아도 자식 프로세스가 남을 수 있었다
- 보고서 링크를 누르면 보고서가 메인 게시판 화면을 덮어 버렸다
앱 로그에는 웹 빌드 도구의 잠금 충돌도 세 번 남아 있었다. 웹 서버가 언제 준비됐는지, 누구 소유인지, 데이터가 언제 바뀌는지, 창이 언제 열리고 닫히는지를 각각 따로 설계하지 않은 탓이었다.
계약을 하나씩 좁혔다
고친 방식은 단순했다. 앱은 자기가 직접 띄운 서버만 쓴다. 서버가 떴는지는 상태 응답과 첫 화면의 표식을 함께 보고 판단한다. 데이터는 임시 파일에 다 쓴 뒤 한 번에 바꿔치기해서 반쯤 쓴 파일이 보이지 않게 한다. 보고서는 메인 창이 아니라 별도 창에서 연다. 앱을 여러 번 실행해도 창은 하나만 뜬다. 보고서는 HTML로 저장하거나 인쇄할 수 있고, 메뉴의 데이터 다시 읽기로 카탈로그와 프로필을 다시 분석한다.
마지막 감사는 심각한 회귀가 없다고 보고했다. 프로세스 트리, 코드 서명, 별도 보고서 창, HTML 저장을 실제로 확인했고 테스트는 27개였다. 남은 건 강제 종료 때 프로세스 묶음 정리, 반복해서 연 보고서 창의 감시자 해제, 자식 프로세스에 넘기는 환경 변수 제한 같은 하드닝 과제다.
배운 것
개발자의 앱과 사용자의 앱은 다르다. 그리고 앱을 앱답게 만드는 건 독립된 창이 아니었다. 그 창 뒤의 서버가 누구 것인지, 준비됐는지 어떻게 아는지, 데이터를 언제 바꾸는지, 닫으면 무엇이 남는지라는 계약이었다. 코드가 있거나 화면이 열렸다는 것만으로는 완성이 아니다. 독립 창, 서버 소유권, 보고서 창, 저장, 종료까지 실제로 써 봐야 완성이다.