Nebula를 만들며: 잠깐 띄운 앱을 다시 이어 쓸 수 있는 환경으로
목차
작은 웹 앱은 실행 명령 하나로 띄울 수 있지만 다른 사람에게 넘기려면 다음 실행에도 무엇이 남는지 정해야 한다. 내가 만드는 Nebula는 이런 앱을 배포하고 같은 주소로 공유하기 위한 샌드박스 프로젝트다. 개발하면서 앱의 이름과 소유 관계, 지금 실행 중인 컨테이너, 앱이 만든 데이터를 각각 다른 수명으로 다루게 됐다.
여기서 샌드박스는 시험용 앱 하나를 실행하고 관리하는 단위다. 잠깐 확인하고 지울 수도 있고 결과를 남겨 다음 실험에 이어 쓸 수도 있다. 둘 다 지원하려면 “실행됐다” 이후의 책임을 정해야 했다.
실행한 앱과 공유하는 앱 사이
다음은 설계 판단을 설명하기 위한 가상 사례다. 파일을 올리면 간단한 분석 결과를 보여 주는 앱을 만들었다고 하자. 첫날에는 개발자가 직접 실행하고 화면을 확인하면 충분하다. 다음 날 다른 사람이 같은 결과를 보려 하면 질문이 늘어난다.
앱을 다시 띄워도 같은 주소로 들어올 수 있는가. 새 버전이 잘못되면 이전 버전을 고를 수 있는가. 앱을 바꾸는 동안 업로드한 파일과 결과는 어떻게 되는가.
이 질문들은 실행 명령의 옵션만으로 답하기 어렵다. 컨테이너를 새로 만들면 실행 객체는 바뀌지만 사용자가 찾아오는 앱의 정체성까지 바뀔 이유는 없다. 반대로 앱의 이름이 같다는 이유만으로 데이터까지 이전 시점으로 돌아가지는 않는다.
Nebula에서는 앱을 소유하는 공간인 워크스페이스를 두고 그 안에서 앱을 관리한다. 사용자는 앱의 주소를 이용하고 플랫폼은 현재 실행 대상으로 요청을 전달한다. 이렇게 앱을 찾는 기준을 실행 객체와 분리하면 컨테이너 교체를 공유 주소의 변경과 따로 다룰 수 있다. 주소가 유지된다는 사실이 교체 중 무중단까지 뜻하지는 않는다.
서로 다른 세 가지 수명
구현을 이해할 때는 “앱이 살아 있다”는 말을 아래처럼 나누는 편이 정확했다.
| 구분 | 맡는 일 | 바뀌거나 끝나는 시점 |
|---|---|---|
| 앱의 정체성과 관리 상태 | 이름, 소유 관계, 배포 이력과 현재 실행 대상 관리 | 배포·공유·삭제 같은 관리 작업 |
| 런타임 | 선택한 앱 버전을 실제로 시작하고 멈춤 | 재배포·재시작으로 실행 객체가 교체될 때 |
| 앱 데이터 | 업로드 파일과 계산 결과 등 앱이 만든 내용 보관 | 데이터 변경·내보내기·정리 정책에 따라 결정 |
런타임은 앱을 실제로 실행하는 수단이다. Nebula는 실행 요청을 인터페이스로 전달하고 런타임이 시작 결과를 돌려주도록 구성했다. 앱의 소유 관계나 배포 이력까지 실행기 안에 넣지 않기 위해서다. 실행 방식을 바꾸더라도 앱을 관리하는 쪽의 판단 기준을 유지하려는 선택이다.
관리 상태와 앱 데이터도 구별했다. “어떤 버전을 누가 배포했는가”는 플랫폼이 기억해야 한다. “앱이 어떤 분석 결과를 만들었는가”는 앱의 저장 공간에 속한다. 플랫폼의 상태 파일을 보존하는 일과 앱 데이터를 보존하는 일은 대상부터 다르다.
이 구분은 기능을 추가할 때도 기준이 된다. 재시작은 실행기를 다시 부르는 작업이지만 복구는 무엇을 어느 시점으로 돌릴지 먼저 고르는 작업이다. 실행 성공만 보고 복구가 끝났다고 판단할 수 없다.
이전 버전으로 돌아가도 결과 파일은 그대로일 수 있다
가상 사례의 앱을 첫 버전에서 두 번째 버전으로 바꿨다고 하자. 새 버전이 결과를 잘못 표시해서 첫 버전으로 되돌리고 싶다. Nebula의 배포 이력에는 다시 실행할 버전을 선택하기 위한 정보가 남는다. 이 이력을 이용하는 롤백과 앱 데이터의 시점 복원은 별개다.
아래는 실행 결과가 아니라 두 책임을 구분하기 위한 예상 상태다. 버전을 교체하는 동안 같은 저장 공간을 계속 사용하고 별도의 데이터 복원은 하지 않는다고 가정했다.
| 순서 | 실행하는 앱 버전 | 저장된 내용 |
|---|---|---|
| 첫 배포 | 첫 버전 | 업로드 파일과 첫 분석 결과 |
| 두 번째 배포 후 새 결과 저장 | 두 번째 버전 | 기존 파일과 새로 쓴 결과 |
| 앱 버전만 롤백 | 첫 버전 | 두 번째 버전이 쓴 결과도 남아 있음 |
마지막 행에서 첫 버전은 두 번째 버전이 만든 데이터를 읽게 된다. 데이터 형식이 호환되면 계속 쓸 수 있다. 두 번째 버전이 저장 형식까지 바꿨다면 첫 버전이 실행돼도 정상 동작하지 않을 수 있다. 앱 버전 선택과 데이터 호환성을 함께 확인해야 하는 이유다.
반대로 데이터를 매번 과거로 되돌리면 두 번째 버전에서 새로 만든 정상 결과까지 잃을 수 있다. 그래서 롤백에 모든 복구 의미를 한꺼번에 넣기보다 어떤 상태를 되돌리는지 구분하는 쪽을 택했다.
실험은 가볍게 끝내고, 남길 결과는 먼저 꺼내기
데이터의 기본 수명에도 선택이 필요했다. 실험용 앱을 쉽게 만들 수 있게 하면서 모든 데이터를 계속 보관하면 앱을 지운 뒤에도 관리할 저장 공간이 쌓인다. 반대로 실행이 끝날 때 즉시 지우면 남길 결과를 꺼낼 기회가 없다.
Nebula의 기본 데이터 수명은 샌드박스에 묶고 보존할 결과는 삭제 전에 내보내는 방향으로 정했다. 앱 전용 저장 공간을 DataSpace라고 부른다. 임시 앱을 장기 데이터 보관소로 키우는 부담을 줄이는 대신, 사용자가 남길 결과를 삭제 전에 판단해야 하는 선택이다.
이 순서에는 의미가 있다. 앱 삭제 뒤 물리적인 정리가 잠시 늦어진다고 해도 그 시간을 다시 내보낼 수 있는 기간으로 약속해서는 안 된다. 사용자에게 제공하는 보존 절차는 삭제 전에 결과를 꺼내는 것이다. 내부 정리가 늦다는 사실에 기대어 복구를 설계하면 관리 작업과 사용자 기대가 어긋난다.
가상 사례에서 분석 결과를 계속 참고하려면 먼저 내보내고 그다음 실험 앱을 지운다. 내보낸 자료로 다시 환경을 만들려면 대상 저장소와 앱 버전의 호환성도 확인해야 한다. 파일을 하나 얻었다는 사실만으로 다시 사용할 환경까지 완성되지는 않는다.
다음 실행에서 무엇을 이어받을까
Nebula를 만들며 실행 대상과 별도로 남겨야 할 정보를 구체적으로 다루게 됐다. 같은 앱을 찾을 주소와 소유 관계, 다시 선택할 배포 버전, 보존할 데이터는 서로 다른 이유로 남는다. 이 글에서 설명한 것은 그 설계와 구현의 책임 구분이며 특정 운영 환경에서 무중단이나 재해 복구 성과를 측정한 결과는 아니다.
임시 미리보기 환경이나 작은 자동화 도구에도 같은 기준을 적용할 수 있다. 실행 객체를 하나 교체해 본다고 가정하고 사용자가 다음에도 같은 주소로 들어와야 하는지, 같은 데이터를 봐야 하는지 나누어 보면 된다. 남아야 할 것이 정해지면 그것을 누가 보관하고 어떤 작업이 끝내도 되는지도 정하기 쉬워진다.