원자적 업데이트와 오류 복구: 일부만 받은 버전을 실행하지 않는 법
여러 파일을 별도로 준비하되 완전한 이전 버전이나 완전한 새 버전만 실행하고, 첫 실행 실패와 영속 데이터 변경까지 고려해 복구 경계를 설계한다.
목차
표준·구현·측정·해석 표시는 무엇인가요?
- 표준웹 표준이나 언어 명세가 정한 동작
- 구현특정 기술이나 브라우저가 실제로 구현한 동작
- 측정명시한 환경에서 직접 실행해 관찰한 결과
- 해석앞선 근거에서 도출한 설계 판단
- 미확인아직 공식 근거나 재현 결과를 확인하지 못한 내용
30초 요약
원자적 업데이트는 여러 파일을 한 네트워크 요청으로 받는다는 뜻이 아니다. 다운로드가 중간에 끊겨도 사용자에게는 완전한 이전 버전 또는 완전한 새 버전만 실행되게 하는 성질이다.
반복해서 기억할 문장은 이것이다.
받는 동안은 이전 버전, 전부 준비된 뒤에만 새 버전.
후보 발견 → 별도 준비 → 전체 파일 검증 → 준비 완료
→ 실행 후보 전환 → 첫 실행 확인 → 성공 유지 또는 실패 격리·복구완전하게 받았다는 사실과 정상 동작한다는 사실도 다르다. 새 코드는 기기 상태와 함께 실제로 시작해 봐야 하며, 코드를 이전 버전으로 바꿔도 이미 바뀐 로컬 자료는 자동으로 되돌아가지 않는다.
원자성은 한 번에 다운로드가 아니라 한 버전만 보이는 성질이다
보이는 앱 상태를 단순하게 쓰면 다음 두 가지만 허용한다.
보이는 상태 ∈ {완전한 이전 업데이트, 완전한 새 업데이트}다음과 같은 혼합 상태는 허용하지 않는다.
새 JavaScript + 이전 이미지 + 누락된 글꼴
이전 JavaScript + 새 설정 파일다운로드는 파일마다 나뉠 수 있고 이미 가진 동일 자산을 재사용할 수도 있다. 원자성은 전송 횟수의 성질이 아니라 어떤 완전한 파일 묶음을 실행 가능 상태로 보이게 하는가의 성질이다.
전원이 꺼지거나 네트워크가 끊겨도 현재 실행 후보를 다운로드 중인 파일로 바로 덮어쓰지 않는다. 새 묶음은 별도 준비 영역에서 완성하고, 모든 필수 파일과 식별 관계를 검증한 뒤에만 실행 후보가 된다.
준비와 활성화를 분리한다
현재 활성: update-A
별도 준비:
update-B manifest ✓
update-B JavaScript ✓
update-B image-1 ✓
update-B font-1 다운로드 중
실행 선택: update-A 유지마지막 글꼴까지 받고 검증한 뒤에야 update-B = 준비 완료라고 기록한다. 다음 시작이나 명시적 다시
불러오기에서 실행 후보를 B로 바꾸는 일을 활성화라고 부른다.
여기서 상태 기계는 가능한 상태와 그 사이 전환 규칙을 정리한 모델이다. 이 모델은 어느 전환에서도 반드시 지켜야 할 규칙인 다음 불변 조건을 가진다.
준비 중인 업데이트는 실행 대상으로 선택하지 않는다.준비 완료표식은 모든 필수 파일과 매니페스트 검증 뒤에만 기록한다.- 활성화가 중단돼도 다음 시작에서 A 또는 B 중 완전한 한 묶음을 선택할 수 있다.
- 파일 이름 하나가 아니라 불변 업데이트 ID로 상태를 연결한다.
준비 완료와 정상 실행은 다른 상태다
파일 해시와 서명이 맞으면 전송 중 내용과 승인한 게시자를 확인할 수 있다. 그러나 다음 문제는 실행해야 드러난다.
- JavaScript가 시작하자마자 존재하지 않는 값을 읽는다.
- React 첫 화면을 계산하는 중 오류가 난다.
- 서버 응답 형식이 새 코드의 예상과 다르다.
- 이전 코드가 남긴 로컬 자료를 새 코드가 읽지 못한다.
- 특정 기기·운영체제에서만 네이티브 호출이 실패한다.
따라서 상태를 하나 더 나눈다.
준비 완료: 파일 묶음이 완전하고 검증됨
활성: 이번 시작에서 선택되어 실행 중
성공 확인: 정한 최소 시작 기준을 통과함
실패: 시작 기준 전에 치명적 오류가 확인됨“성공 확인”은 무엇을 확인했는지 이름과 함께 기록해야 한다. 첫 화면 표시, 로그인 전 초기화, 저장소 열기와 같은 기준은 답하는 질문이 다르다.
성공 확인점은 완전한 건강 증명이 아니다
현재 구현의 판단 흐름을 개념만 남기면 다음과 같다.
치명적 JavaScript 오류
├─ 첫 화면 전 + 이 업데이트의 첫 실행
│ ├─ 현재 업데이트를 로컬 실패로 표시
│ ├─ 짧은 시간 새 업데이트 확인
│ └─ 없거나 실패하면 최근 성공 업데이트 시도
└─ 첫 화면 뒤 또는 이전에 한 번 표시 성공
├─ 짧은 시간 새 수정 업데이트 확인
└─ 원래 오류를 다시 던지고 다음 시작의 수정본을 기대현재 문서의 더 구체적인 시간 경계도 구현 세부다. 첫 렌더 뒤 10초를 넘겨 발생한 치명적 오류는 이 복구 흐름이 잡지 않으며, 복구 중 새 업데이트를 기다리는 타이머는 5초다. 이 숫자를 제품 건강의 보편 법칙으로 쓰지 않는다.
첫 화면 표시는 “아무 코드도 실행되기 전에 실패했는가”를 가르는 현재의 보수적 대리 신호다. 결제, 검색, 알림, 백그라운드 작업과 모든 자료 변경이 정상이라는 증명은 아니다. 앱은 도구의 확인점과 별도로 핵심 흐름의 오류율과 성공률을 관찰해야 한다.
최근 성공 업데이트는 지역 안전망이다
최근 성공 업데이트는 이 기기에서 이전에 최소 시작 기준을 통과한 완전한 업데이트다. 단순히 서버에 게시된 이전 번호나 다운로드 시각이 가장 오래된 파일을 뜻하지 않는다.
update-A: 이 기기에서 성공 확인
update-B: 준비 완료, 첫 실행 전
update-C: 준비 중B가 첫 화면 전에 실패하면 A가 지역 복구 후보가 될 수 있다. C는 완전하지 않으므로 실행 후보가 아니다. 다른 기기에서는 B가 성공했을 수 있으므로 “최근 성공”은 서버 전체가 아니라 기기 로컬 상태일 수 있다.
안티브리킹은 잘못된 업데이트가 앱 시작 직후 계속 충돌해 새 수정본조차 받을 기회를 잃는 상태를 줄이는 안전장치다. 모든 버그를 숨기거나 사용자에게 충돌을 전혀 보이지 않게 하는 기능은 아니다. 현재 Expo 문서도 사용자가 충돌을 볼 수 있으며 내장 복구를 테스트 대신 믿지 말라고 명시한다.
코드를 되돌려도 영속 상태는 자동으로 되돌아가지 않는다
영속 상태는 앱을 종료해도 남는 AsyncStorage 값, 파일과 로컬 데이터베이스 자료다. 새 업데이트가 이 자료 구조를 바꾸면 이전 코드로 실행 대상을 바꾸는 것만으로 과거 상태가 복원되지 않는다.
예를 들어 새 코드가 다음처럼 자료를 바꿨다고 하자.
이전: { "name": "Mina" }
전환기: { "name": "Mina", "profile": { "displayName": "Mina" }, "schema": 2 }schema는 현재 자료 모양을 구분하는 형식 버전이다. 새 형식에서 name을 곧바로 없애면 이전
코드는 그 값만 찾다가 실패할 수 있다. 안전한 변경은 보통 단계를 나눈다.
1. 새 코드는 `profile.displayName`이 없으면 이전 `name`도 읽는다.
2. 이전 코드가 지원 대상인 동안은 저장할 때 `name`과 `profile`을 함께 갱신한다.
3. 지원 중인 이전 코드가 사라진 뒤 오래된 형식을 정리한다.이것은 조건부 권장 패턴이다. 자료 크기, 개인정보 삭제 요구와 마이그레이션 비용에 따라 다른 전략이 필요할 수 있다. 핵심은 코드 버전 선택과 자료 상태 전환을 하나의 마법 같은 롤백으로 생각하지 않는 것이다.
React 오류 경계와 업데이트 복구는 책임이 다르다
React 오류 경계
목적: 화면 일부가 사라지는 대신 대체 UI 표시
상태: 같은 JavaScript 업데이트를 계속 실행할 수 있음
업데이트 오류 복구
목적: 시작 불가능한 코드 묶음을 다시 선택하지 않음
상태: 업데이트 ID의 실행 성공·실패와 대체 후보 관리오류 경계가 오류를 화면 안에서 처리하면 네이티브 복구를 일으킬 치명적 오류가 되지 않을 수 있다. 반대로 최상위 React 화면인 루트가 준비되기 전 오류나 네이티브 충돌은 오류 경계가 표시할 화면 자체가 없을 수 있다. 둘 중 하나를 빼는 선택이 아니라 실패 범위에 맞춰 함께 둔다.
Web, React, React Native의 연결점
Web 배포도 새 JavaScript·스타일·이미지를 준비하는 동안 현재 릴리스가 가리키는 완전한 산출물 묶음을 유지하고, 준비 완료 뒤 불변 릴리스 ID가 가리키는 대상을 바꾸는 모델을 사용할 수 있다. 부분 업로드 파일을 현재 경로에 곧바로 노출하면 같은 혼합 버전 문제가 생긴다.
React에서는 오류 경계가 렌더링 실패를 화면 단위로 격리하고 상태 복구 UI를 제공한다. 하지만 브라우저나 React Native가 어느 JavaScript 산출물을 시작할지 고르는 책임은 React 밖에 있다.
React Native OTA에서는 네이티브 업데이트 클라이언트가 파일 묶음의 준비·실행 후보 선택과 초기 치명적 오류 복구를 맡는다. JavaScript 애플리케이션은 핵심 흐름 관측, 사용자 자료 호환성과 안전한 다시 시도 화면을 맡는다.
복구 상태를 실행 조합과 함께 관찰한다
최소 관측 항목은 다음과 같다.
| 항목 | 답하는 질문 |
|---|---|
| 현재 업데이트 ID·빌드·런타임 | 어떤 실행 조합인가? |
| 내장 업데이트 실행 여부 | 다운로드본이 아닌 로컬 기준점을 썼는가? |
| 준비 실패 단계·자산 ID | 매니페스트·다운로드·해시 중 어디서 멈췄는가? |
| 첫 화면 표시 여부와 시작 시간 | 현재 복구 경계 전에 실패했는가? |
| 실패 표시한 업데이트 ID | 다음 시작에서 무엇을 제외했는가? |
| 비상 시작 여부·이유 | 왜 내장 업데이트로 대체했는가? |
| 영속 상태 스키마 버전 | 어떤 자료 형식과 코드가 만났는가? |
복구 자체가 충돌 보고를 지우면 안 된다. 사용자가 다음 시작에서 회복했더라도 어떤 업데이트가 어떤 단계에서 실패했고 무엇으로 대체됐는지 남겨야 수정본을 만들 수 있다.
실패를 주입해 확인할 시나리오
정상 경로 하나만 확인하면 복구 코드는 검증되지 않는다.
- 큰 자산 다운로드 중 네트워크를 끊고 이전 업데이트가 계속 시작되는지 본다.
- 자산 바이트를 바꿔 해시 실패가 준비 완료로 기록되지 않는지 본다.
- 첫 화면 전에 의도적 치명 오류를 만들고 실패 표시와 최근 성공 후보 선택을 본다.
- 첫 화면 뒤 오류에서는 위험한 자동 이전 버전 실행을 하지 않는지 본다.
- 새 자료 형식을 저장한 뒤 이전 코드와 수정 코드를 각각 실행해 호환성을 본다.
- 내장·다운로드 업데이트가 모두 실행 불가능할 때 사용자 안내와 진단 신호를 본다.
테스트용 업데이트 ID와 기기 저장소를 분리해 운영 사용자 자료를 건드리지 않는다. 현재 Expo의 5초·10초 경계를 검증한다면 라이브러리 버전과 설정도 결과에 함께 기록한다.
자주 실패하는 설계
다운로드한 파일부터 현재 경로에 덮어쓴다
중단되면 서로 다른 버전이 섞인다. 별도 준비 영역과 준비 완료 표식 뒤 실행 후보 전환을 사용한다.
해시 검증 성공을 건강 확인으로 쓴다
파일 일치만 확인할 뿐 렌더링·자료 계약은 실행하지 않았다. 시작 기준과 핵심 흐름 신호를 별도로 둔다.
첫 화면 표시를 전체 앱 성공으로 본다
현재 Expo 복구의 보수적 분기 신호이지 모든 기능의 건강 증명이 아니다. 이후 비동기 오류와 핵심 업무 성공률도 관찰한다.
이전 JavaScript를 고르면 로컬 자료도 돌아간다고 생각한다
AsyncStorage·파일·데이터베이스는 그대로 남는다. 앞뒤 버전 읽기 호환성과 수정본 경로를 설계한다.
자동 복구를 테스트 대신 믿는다
현재 복구 동작은 변경될 수 있는 최후 안전장치다. 운영과 비슷한 저장 상태, 느린 네트워크와 시작 오류를 직접 재현한다.
원자적 업데이트와 복구를 설계하는 순서
- 한 업데이트를 이루는 매니페스트와 필수 파일 경계를 정한다.
- 현재 실행 묶음과 새 다운로드의 저장·상태를 분리한다.
- 전체 파일 검증 뒤에만 준비 완료를 기록한다.
- 활성화가 중단돼도 완전한 한 버전을 고를 수 있게 한다.
- 첫 실행 성공·실패 기준과 실패 후보 재선택 금지 규칙을 정한다.
- 코드 이전 버전 실행과 영속 자료 호환성을 따로 검증한다.
- 불완전 다운로드·첫 화면 전후 오류·비상 시작을 주입하고 관측한다.
핵심은 새 버전을 빨리 켜는 것이 아니라, 불완전한 버전을 절대 켜지 않고 실패한 완전한 버전에서도 다시 수정할 기회를 남기는 것이다.
한 문장으로 다시 설명하기
원자적 업데이트는 파일을 하나씩 내려받더라도 완전한 이전 버전이나 완전한 새 버전만 실행되게 준비와 활성화를 분리하는 설계다. 모든 파일 검증은 실행 후보가 됐다는 뜻일 뿐 건강 보증이 아니며, 첫 실행 실패를 격리하고 최근 성공 또는 수정 업데이트를 선택할 경로가 필요하다. 코드 선택을 되돌려도 영속 자료는 돌아가지 않으므로 상태 호환성과 복구 관측을 별도로 설계한다.
스스로 확인하기
- 원자적 업데이트가 “파일을 한 요청으로 받는다”는 뜻이 아닌 이유는 무엇인가?
준비 중,준비 완료,활성,성공 확인,실패는 각각 무엇을 뜻하는가?- 모든 파일의 해시가 맞아도 정상 동작을 확정할 수 없는 이유는 무엇인가?
- 현재 expo-updates가 첫 화면 표시 전후 오류를 다르게 다루는 이유는 무엇인가?
- 최근 성공 업데이트는 서버의 이전 번호와 어떻게 다른가?
- React 오류 경계와 네이티브 업데이트 복구는 어떤 실패를 각각 다루는가?
- 이전 코드로 돌아가도 영속 상태 마이그레이션이 위험할 수 있는 이유는 무엇인가?
- 불완전 다운로드와 첫 실행 실패를 검증하려면 어떤 오류를 의도적으로 주입해야 하는가?
Active recall
기억에서 꺼내 보기
답을 쓰지 않아도 됩니다. 먼저 머릿속으로 답한 뒤 펼쳐서 정답·이유·흔한 오해를 비교하세요.
01새 업데이트의 JavaScript는 받았지만 이미지 하나를 받다가 앱이 종료됐다면 다음 시작에서 받은 JavaScript만 실행해도 될까?
정답
안 된다. 완전한 이전 업데이트를 계속 실행하고, 새 업데이트의 모든 필수 파일이 준비·검증된 뒤에만 새 묶음을 실행 후보로 활성화해야 한다.
관련 설명 다시 읽기왜 그런가
원자성은 다운로드 요청이 하나라는 뜻이 아니라 사용자에게 완전한 버전만 보인다는 뜻이다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
02모든 파일을 내려받고 해시 검증을 통과했으면 새 업데이트가 정상 동작한다고 확정할 수 있을까?
정답
확정할 수 없다. 파일 준비 완료는 실행 가능 후보라는 뜻이며, 실제 시작과 핵심 동작을 별도로 확인해야 한다.
관련 설명 다시 읽기왜 그런가
전송 무결성은 렌더링 오류, 잘못된 자료 계약이나 영속 상태 호환성을 검증하지 않는다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
03현재 expo-updates에서 첫 화면이 한 번 나타났으면 업데이트의 모든 기능과 데이터 변경이 안전하다고 증명될까?
정답
아니다. 현재 오류 복구가 자동 이전 버전 실행 여부를 정하는 데 쓰는 경계일 뿐 전체 건강 검사는 아니다.
관련 설명 다시 읽기왜 그런가
첫 화면 뒤에도 비동기 작업과 영속 상태 변경에서 오류가 날 수 있고 현재 복구 규칙도 변경될 수 있다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
04새 JavaScript가 로컬 자료 구조를 바꾼 뒤 충돌하면 이전 JavaScript로 돌아가기만 해도 안전할까?
정답
반드시 그렇지 않다. 이전 코드가 새 자료 구조를 읽지 못하면 더 실패할 수 있으므로 자료 변경도 앞뒤 버전 호환성과 복구 절차를 가져야 한다.
관련 설명 다시 읽기왜 그런가
코드 선택 포인터와 AsyncStorage·파일·데이터베이스 상태는 서로 다른 저장소다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
05React 오류 경계가 있으면 시작 전에 발생한 모든 치명적 오류와 업데이트 교체까지 자동 복구할까?
정답
아니다. 오류 경계는 자식 렌더링 오류에 대체 화면을 보여 주는 React 경계이고, 업데이트 실패 표식·다른 실행 후보 선택은 네이티브 업데이트 클라이언트의 별도 책임이다.
관련 설명 다시 읽기왜 그런가
화면 일부의 오류 격리와 앱 실행 코드 묶음의 복구는 실패 범위와 상태가 다르다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
출처와 검증 범위
아래 날짜는 링크를 마지막으로 열어 본 날입니다. 문서 상단의 검증일은 글의 설명과 적용 범위를 다시 확인한 날입니다.
- Expo Updates v1Expo · 표준 · 확인 2026-08-04
- Error recoveryExpo · 공식 문서 · 확인 2026-08-04
- UpdatesExpo · 공식 문서 · 확인 2026-08-04
- Downloading updatesExpo · 공식 문서 · 확인 2026-08-04
- Component — Catching rendering errors with an error boundaryReact · 공식 문서 · 확인 2026-08-04