서비스 인프라

앱 심사와 단계적 출시, 되돌릴 수 없는 배포

설치된 앱은 서버 파일처럼 한 번에 바꾸기 어려워요. 배포 경로와 옛 버전의 수명, 서버에 남길 판단을 함께 살펴봐요.

이 글의 목차배포권이 남에게 있는 세계4
  1. 배포권이 남에게 있는 세계
  2. 되돌릴 수 없다는 제약이 설계를 바꾼다
  3. 옛 버전이 영원히 남는다
  4. 저는 무엇을 서버에 두었나

웹에서는 제가 배포를 정해요. 고치고 올리면 다음 방문자부터 새 화면을 봐요. 앱은 그렇지 않아요. 만든 것을 스토어에 올리면 심사를 기다려야 하고, 통과해도 사용자가 내려받아야 반영돼요. 배포 시점이 제 손을 두 번 떠나는 셈이에요.

심사와 대기가 앱 배포의 특징으로 자주 이야기되지만, 운영에서 실제로 설계를 바꾸는 제약은 다른 쪽이에요. 이미 설치된 앱은 회수할 수 없어요.

배포권이 남에게 있는 세계

2008년 7월 10일 Apple은 iPhone의 App Store를 열면서 500개가 넘는 앱을 함께 공개했어요. 개인이 만든 프로그램이 심사를 거쳐 전 세계에 배포되는 통로가 이때 생겼고, 그 통로를 운영자가 관리한다는 구조도 함께 정해졌어요.

앱에는 사용자에게 보이는 버전과 업로드를 구별하는 빌드 번호가 있어요. 같은 출시 버전을 준비하면서도 빌드를 여러 번 올릴 수 있지만, 업로드 식별 규칙은 지켜야 해요. 더 큰 제약은 새 바이너리가 심사와 사용자 업데이트를 거쳐야 한다는 점이에요. 수정 파일을 올렸다고 모든 기기의 코드가 그 자리에서 바뀌지는 않아요.

되돌릴 수 없다는 제약이 설계를 바꾼다

웹은 이전 산출물을 다시 제공하도록 바꾸기 쉬워요. 그래도 이미 열린 탭이나 브라우저 캐시, 서비스 워커가 이전 코드를 계속 쓸 수 있어요. 서버를 되돌렸다고 모든 방문자의 실행 상태가 동시에 바뀌는 것은 아니에요. 앱에서는 사용자가 설치한 바이너리가 오래 남는다는 제약이 더 뚜렷해요.

앱에는 그런 스위치가 없어요. Google도 단계적 배포를 중단하는 기능을 두면서 그 뜻을 분명히 적어 두었어요. 중단하면 추가 사용자에게는 그 버전이 가지 않지만, 이미 받은 사용자는 그 버전에 그대로 남는다는 것이에요. 스토어에서 새 버전 배포를 멈출 수는 있어도, 이미 내려받아 실행 중인 앱을 되돌릴 방법은 없어요. 고친 버전을 다시 심사받아 올리고, 사용자가 그것을 내려받기를 기다려야 해요. 그동안 문제가 있는 버전은 사용자의 기기에서 계속 돌아요.

배포를 멈춰도 설치된 앱은 남아요

예시 기기 10대 중 2대가 새 버전을 받은 상태예요.

새 배포: 진행 중

옛 버전 설치 기기8

새 버전 설치 기기2

단계적 배포를 중단해도 이미 새 버전을 받은 기기는 그 버전을 계속 사용해요. 배포 중단은 설치 취소가 아니에요.

Google Play의 단계적 출시를 기기 10대로 단순화한 예시예요. 실제 배포 비율·속도가 아니며, Apple의 수동 다운로드 조건은 별도예요.

결정 위치에 따른 변경 반영 경로 운영 중 즉시 바꿔야 하는 판단을 앱에 고정하면 복구 경로도 심사에 묶인다. 개념 도해 결정 위치에 따른 변경 반영 경로 앱 동작의 결정 경로 앱 고정 ① 앱 실행 설치된 버전 ② 결정값 읽기 앱 번들 ③ 동작 선택 버전 고정 서버 결정 ① 앱 실행 설치된 버전 ② 결정값 조회 서버 응답 ③ 동작 선택 응답별 결정 결정 위치별 변경 반영 순서 앱 고정 ① 코드 수정 ② 심사·배포 ③ 사용자 갱신 다음 버전 서버 결정 ① 설정 변경 ② 다음 응답 ③ 동작 전환 운영 중 반영 변경 반영 순서 운영 중 즉시 바꿔야 하는 판단을 앱에 고정하면 복구 경로도 심사에 묶인다. SOSHIN · DEV NOTES
앱에 박아 넣은 것은 심사를 거쳐야 바뀌고, 서버가 정하는 것은 지금 바뀌어요.

그래서 앱을 만들 때 반복해서 던지게 되는 질문이 있어요. 이 값을 앱 안에 둘 것인가 서버가 정하게 할 것인가. 화면에 보여 줄 문구, 어떤 기능을 켤지, 어느 서버를 부를지, 얼마나 기다렸다 포기할지 같은 것들이에요. 앱 안에 두면 단순하지만 바꾸려면 심사를 거쳐야 하고, 서버가 정하게 하면 복잡해지지만 문제가 생겼을 때 그 자리에서 끌 수 있어요.

새 기능을 한 번에 모두에게 열지 않고 일부에게만 먼저 여는 단계적 출시가 흔한 것도 같은 이유예요. Apple의 단계적 출시는 자동 갱신을 켜 둔 사용자에게 이레에 걸쳐 나눠 배포하고, 그사이 배포를 멈출 수 있게 해 둬요. 되돌릴 수 없다면 노출되는 범위를 줄이고 퍼지는 속도를 늦추는 것이 사실상 유일한 방어가 돼요.

옛 버전이 영원히 남는다

옛 클라이언트가 얼마나 오래 남는지도 설계에 영향을 줘요. 웹에서도 오래 열린 화면을 고려해야 하지만, 앱은 사용자가 업데이트하지 않은 버전이 훨씬 오래 서버를 부를 수 있어요. 응답에서 필드를 지우거나 뜻을 바꾸면 새 앱은 잘 되는데 옛 앱만 깨질 수 있죠.

비교할 것웹 배포앱 배포
새 코드 제공서버 배포를 직접 바꿀 수 있음스토어 절차와 기기 업데이트를 거침
되돌리기이전 파일 제공으로 전환 가능설치된 앱을 즉시 회수하기 어려움
옛 버전열린 탭과 캐시에 남을 수 있음업데이트 전까지 장기간 남을 수 있음

마지막 줄이 서버 쪽 설계를 계속 제약해요. 응답 형식을 바꿀 때 옛 앱이 무시하고 넘어갈 수 있는 방식으로 더하는 편이 안전하고, 필드를 지우거나 뜻을 바꾸는 변경은 지원을 끊기로 한 버전 범위를 먼저 정한 뒤에야 할 수 있어요.

저는 무엇을 서버에 두었나

작은 앱을 만들면서 앱에 박지 않고 서버가 정하게 남겨 둔 것들이 있어요. AI 응답을 어느 경로로 받을지, 얼마나 기다렸다 대체 경로로 넘길지, 어떤 기능을 지금 열어 둘지 같은 판단이에요. 앱 안에 두면 코드가 훨씬 단순해졌겠지만, 그렇게 했다면 앞선 글에서 이야기한 모델 교체 작업을 하지 못했을 것이에요. 장비를 손보는 동안 대체 경로로 넘기는 판단이 앱 안에 박혀 있었다면 그 판단을 바꾸는 데 심사가 필요했을 테니까.

같은 이유로 사용자에게 보여 줄 안내 문구도 되도록 서버에서 내려 줘요. 문구 하나 고치자고 심사를 기다리는 상황이 반복되면 결국 고치지 않게 돼요.

되돌릴 수 없는 경로에서는 무엇을 그 경로에 태울지가 곧 설계였어요. 웹에서는 자유롭게 정할 수 있던 것들이, 여기서는 되돌릴 수 있는 쪽과 없는 쪽을 나누는 기준이 됐어요.

소신을 상징하는 까마귀 목판화 일러스트
작성자소신 · Soshin

웹과 서버를 만들고, 개발하며 배운 것들을 글로 남깁니다.

좌우로 움직여 보세요