모바일 앱 개발 핵심 개념 지도: 화면 생명주기에서 스토어 배포까지
웹을 만들던 방식 그대로 앱을 만들면 대개 두 지점에서 막힙니다. 하나는 화면이 언제 살아 있고 언제 죽는지 앱이 마음대로 정한다는 것이고, 다른 하나는 만든 것을 바로 내보낼 수 없다는 것입니다. 브라우저에서는 새로고침이 해결하던 문제를 앱에서는 상태 복원과 심사 대기가 대신합니다.
이 문서는 모바일 앱 개발의 중요한 개념을 한곳에서 찾기 위한 지도입니다. 특정 프레임워크의 API가 아니라, 화면이 살아가는 방식과 기기라는 제약, 그리고 스토어를 거치는 배포에 대한 개념을 중심에 뒀습니다. 각 항목은 한두 문장으로 범위를 잡고, 자세한 설명이 필요한 주제는 별도의 심화 글로 연결합니다. 처음부터 끝까지 외울 필요는 없습니다. 낯선 용어가 나왔을 때 어느 영역에 속하고 무엇과 연결되는지 확인하는 기준점으로 사용하는 편이 좋습니다.
플랫폼과 기술 선택
-> 화면 생명주기
-> 상태와 데이터
-> 네트워크와 오프라인
-> 저장과 보안
-> 성능과 배터리
-> 권한과 시스템 연동
-> 테스트
-> 스토어 배포와 운영플랫폼과 기술 선택
- 네이티브: 플랫폼이 제공하는 언어와 도구로 만드는 방식입니다. 성능과 최신 기능 접근이 가장 좋지만 두 벌을 만들고 유지해야 합니다.
- 크로스 플랫폼: 하나의 코드로 두 플랫폼을 대상으로 하는 방식입니다. 화면과 로직은 공유되지만 플랫폼 차이는 결국 코드에 드러납니다.
- 웹뷰 기반: 웹 화면을 앱 껍데기에 담는 방식입니다. 배포가 빠른 대신 스크롤과 입력 같은 기본 상호작용에서 이질감이 남습니다.
- 하이브리드 경계: 어디까지 공유하고 어디부터 플랫폼별로 갈지 정하는 선입니다. 대개 화면 전환과 시스템 연동이 갈라지는 지점입니다.
- 네이티브 모듈: 크로스 플랫폼 코드에서 플랫폼 기능을 호출하는 다리입니다. 하나 만드는 순간 두 플랫폼의 빌드 환경을 모두 다뤄야 합니다.
- 플랫폼 차이: 뒤로 가기 버튼, 권한 요청 시점, 알림 동작, 기본 제스처가 서로 다릅니다. 같은 화면을 그대로 두면 한쪽에서는 반드시 어색합니다.
- 디자인 가이드: 각 플랫폼이 권장하는 인터페이스 규칙입니다. 무시하면 사용자가 아는 방식이 통하지 않고 심사에서도 지적을 받습니다.
- 최소 지원 버전: 어느 OS 버전부터 지원할지의 결정입니다. 낮게 잡을수록 사용자는 늘고 쓸 수 있는 API와 테스트 비용은 나빠집니다.
- 기기 파편화: 화면 크기, 성능, 제조사 변형이 넓게 퍼져 있습니다. 개발 기기 한 대에서 잘 도는 것은 아무것도 증명하지 않습니다.
- 화면 밀도: 같은 크기라도 픽셀 수가 다릅니다. 이미지와 여백을 밀도 독립 단위로 다뤄야 기기마다 어긋나지 않습니다.
- 안전 영역: 노치, 상태 바, 홈 인디케이터를 피해야 하는 영역입니다. 하단 고정 버튼이 가장 자주 걸립니다.
- 다크 모드와 접근성 설정: 시스템 설정을 따라야 합니다. 글자 크기 확대를 무시하면 레이아웃이 깨지고 접근성 심사에도 걸립니다.
- 선택의 기준: 팀이 이미 아는 기술, 필요한 기기 기능, 배포 주기를 함께 봅니다. 기술 자체의 우열보다 이 셋이 결과를 더 크게 좌우합니다.
화면 생명주기
- 생명주기: 화면이 생성되고 보이고 가려지고 사라지는 정해진 순서입니다. 웹과 달리 앱은 이 전환을 시스템이 주도합니다.
- 포그라운드와 백그라운드: 사용자가 보고 있는 상태와 뒤로 밀린 상태입니다. 백그라운드에서는 실행 시간과 자원이 크게 제한됩니다.
- 프로세스 종료: 메모리가 부족하면 시스템이 앱을 예고 없이 죽입니다. 사용자는 앱을 껐다고 생각하지 않으므로 다시 열었을 때 그대로여야 합니다.
- 상태 복원: 죽었다 살아난 뒤 사용자가 있던 자리로 돌려놓는 처리입니다. 화면 위치뿐 아니라 입력 중이던 값까지 포함해야 자연스럽습니다.
- 구성 변경: 화면 회전, 글자 크기, 언어 변경으로 화면이 다시 만들어지는 상황입니다. 여기서 상태를 잃으면 사용자는 앱이 고장 났다고 느낍니다.
- 화면 스택: 화면이 쌓이고 뒤로 가기로 벗겨지는 구조입니다. 스택을 어디서 초기화할지 정하지 않으면 뒤로 가기가 예측 불가능해집니다.
- 딥링크: 외부에서 특정 화면으로 바로 들어오는 경로입니다. 중간 화면이 없는 상태로 진입하므로 뒤로 갈 곳을 따로 정해야 합니다.
- 콜드 스타트와 웜 스타트: 완전히 새로 뜨는 경우와 남아 있던 프로세스를 깨우는 경우입니다. 첫인상을 결정하는 것은 콜드 스타트 시간입니다.
- 스플래시: 초기화 동안 보여 주는 화면입니다. 길이를 늘려 로딩을 감추기 시작하면 실제 문제를 놓칩니다.
- 화면 밖 작업: 사용자가 앱을 떠난 뒤에도 끝내야 하는 일입니다. 업로드나 결제 확인은 화면 생명주기가 아니라 별도 실행 단위에 맡겨야 합니다.
- 메모리 경고: 시스템이 자원을 회수하기 전에 보내는 신호입니다. 캐시를 비울 기회이며 무시하면 종료로 이어집니다.
- 다중 창과 분할 화면: 태블릿과 데스크톱 모드에서 앱이 화면 일부만 차지합니다. 고정 크기를 가정한 레이아웃이 여기서 깨집니다.
- 생명주기와 구독: 화면이 사라질 때 구독과 타이머를 정리하지 않으면 누수와 잘못된 갱신이 남습니다. 앱 크래시의 흔한 원인입니다.
상태와 데이터 흐름
- UI 상태: 화면이 지금 무엇을 보여 주고 있는지의 값입니다. 로딩, 성공, 비어 있음, 오류를 모두 표현할 수 있어야 합니다.
- 단방향 데이터 흐름: 상태가 위에서 아래로 흐르고 이벤트가 위로 올라가는 구조입니다. 어디서 값이 바뀌었는지 추적 가능해집니다.
- 상태 호이스팅: 상태를 쓰는 곳보다 위에 두어 여러 화면이 공유하게 하는 기법입니다. 너무 올리면 모든 변경이 넓은 범위를 다시 그립니다.
- 화면 상태와 앱 상태: 이 화면에서만 의미 있는 값과 앱 전체가 공유하는 값입니다. 둘을 섞으면 화면을 닫아도 값이 남거나 반대로 사라집니다.
- 저장 가능한 상태: 프로세스가 죽어도 살아남아야 하는 값입니다. 무엇을 저장할지 목록으로 정해 두지 않으면 복원이 매번 다릅니다.
- 비동기 상태: 네트워크와 디스크 작업의 진행과 결과를 표현합니다. 로딩과 오류를 예외 취급하면 화면의 절반이 처리되지 않은 채 남습니다.
- 경쟁 조건: 늦게 도착한 옛 응답이 새 결과를 덮어쓰는 문제입니다. 요청마다 식별자를 붙이거나 이전 작업을 취소해야 합니다.
- 취소: 사용자가 화면을 떠나면 진행 중인 작업을 멈춥니다. 취소가 없으면 자원과 배터리를 계속 씁니다.
- 불변 데이터: 값을 바꾸지 않고 새로 만들어 교체합니다. 어디서 바뀌었는지 찾는 시간이 크게 줄어듭니다.
- 의존성 주입: 화면이 구현 대신 인터페이스에 기대게 만듭니다. 테스트에서 가짜 구현으로 갈아 끼울 수 있게 하는 전제입니다.
- 리포지토리: 네트워크와 로컬 저장소를 감싸 화면에 하나의 창구로 보여 줍니다. 데이터 출처가 바뀌어도 화면이 모르게 합니다.
- 단일 진실 공급원: 같은 데이터를 두 곳에서 각자 관리하지 않는다는 원칙입니다. 어긋남이 생기면 어느 쪽이 맞는지 판정할 방법이 없습니다.
- 화면 다시 그리기: 상태가 바뀔 때 무엇을 다시 그릴지가 성능을 좌우합니다. 목록 전체를 다시 그리는 습관이 대부분의 버벅임을 만듭니다.
네트워크와 오프라인
- 불안정한 연결: 모바일에서 연결은 항상 끊기고 느려집니다. 연결이 되어 있다는 가정은 코드가 아니라 사무실 환경의 산물입니다.
- 타임아웃: 언제 포기할지 정하는 값입니다. 기본값이 지나치게 길면 사용자는 앱이 멈춘 것으로 받아들입니다.
- 재시도: 일시적 실패를 넘기되 지수적 대기와 흔들림을 함께 씁니다. 즉시 반복하면 신호가 약한 곳에서 배터리만 태웁니다.
- 멱등성: 같은 요청이 두 번 도착해도 결과가 한 번과 같아야 합니다. 재시도가 있는 결제와 주문에서 특히 중요합니다.
- 오프라인 우선: 로컬을 먼저 읽고 쓰고 나중에 서버와 맞추는 설계입니다. 지하철과 엘리베이터에서도 앱이 죽지 않게 만드는 방법입니다.
- 동기화: 로컬 변경과 서버 변경을 합치는 과정입니다. 충돌이 났을 때 무엇이 이기는지 규칙을 먼저 정해야 합니다.
- 충돌 해결: 마지막 쓰기가 이기게 할지, 병합할지, 사용자에게 물을지의 선택입니다. 조용히 덮어쓰면 사용자는 데이터를 잃었다고 느낍니다.
- 캐시 정책: 얼마나 오래 재사용하고 언제 다시 받을지 정합니다. 목록은 캐시하고 잔액은 캐시하지 않는 식으로 항목마다 다릅니다.
- 페이지네이션: 목록을 나눠 받아 메모리와 대역폭을 아낍니다. 커서 방식이 항목 추가·삭제에 안전합니다.
- 이미지 로딩: 크기 조절, 캐시, 취소가 함께 필요합니다. 원본을 그대로 받아 그리면 목록 스크롤이 즉시 무너집니다.
- 페이로드 크기: 모바일 데이터와 배터리를 직접 씁니다. 화면에 안 쓰는 필드를 받아 오고 있는지 한 번은 확인해야 합니다.
- 실시간 연결: 소켓과 푸시 중 무엇을 쓸지의 선택입니다. 소켓은 즉시성이 좋고 백그라운드에서 유지되지 않는다는 제약이 있습니다.
- 네트워크 상태 표시: 오프라인임을 알리고 되돌아왔을 때 다시 시도하게 합니다. 실패를 조용히 삼키는 것이 가장 나쁜 처리입니다.
저장과 보안
- 저장소 선택: 키-값, 파일, 관계형 데이터베이스가 각각의 자리가 있습니다. 구조와 조회 방식이 선택을 정합니다.
- 로컬 데이터베이스: 오프라인 데이터를 다루는 기본 도구입니다. 스키마 변경 시 마이그레이션을 준비하지 않으면 업데이트가 데이터를 날립니다.
- 키-값 저장소: 설정처럼 작고 단순한 값에 씁니다. 큰 데이터를 넣으면 앱 시작 시간이 느려집니다.
- 파일 저장: 이미지와 문서를 다루며 용량 관리가 함께 필요합니다. 지우지 않으면 사용자 기기의 저장 공간을 계속 먹습니다.
- 보안 저장소: 토큰과 자격 증명은 시스템이 제공하는 보안 저장소에 둡니다. 일반 저장소에 넣으면 기기 접근만으로 노출됩니다.
- 토큰 관리: 짧은 접근 토큰과 갱신 토큰을 나누고 갱신 실패를 처리합니다. 갱신 동시 요청이 몰릴 때의 처리도 정해야 합니다.
- 생체 인증: 지문과 얼굴로 잠금을 여는 기능입니다. 인증 수단이지 그 자체로 신원 증명이 아니므로 서버 검증과 짝을 이뤄야 합니다.
- 인증서 고정: 통신 상대의 인증서를 고정해 중간자 공격을 막습니다. 교체 계획 없이 걸면 인증서 만료일에 앱 전체가 죽습니다.
- 난독화와 무결성: 코드 분석과 변조를 어렵게 만듭니다. 막을 수는 없고 비용을 올릴 뿐이라는 전제로 다뤄야 합니다.
- 탈옥과 루팅: 시스템 보호가 해제된 기기에서는 저장소 보호가 성립하지 않습니다. 무엇을 기기에 두지 않을지가 실질적인 대응입니다.
- 개인정보 최소 수집: 필요한 것만 받고 필요한 동안만 둡니다. 수집 항목이 늘수록 심사와 법적 부담이 함께 늘어납니다.
- 로그와 개인정보: 디버깅 로그에 토큰과 개인정보가 섞이기 쉽습니다. 배포 빌드에서 로그 수준을 낮추는 것만으로는 부족합니다.
- 데이터 삭제: 로그아웃과 계정 삭제 시 무엇을 지울지 정합니다. 캐시와 이미지가 남아 다음 사용자에게 보이는 사고가 흔합니다.
성능과 배터리
- 시작 시간: 앱을 열고 첫 화면이 쓸 수 있게 되기까지의 시간입니다. 초기화 작업을 시작 경로에서 빼는 것이 가장 큰 개선입니다.
- 프레임 예산: 부드럽게 보이려면 한 프레임을 정해진 시간 안에 그려야 합니다. 이 예산을 넘기는 작업이 곧 버벅임입니다.
- 메인 스레드: 화면을 그리는 스레드에서 무거운 일을 하면 즉시 멈춤으로 보입니다. 파일과 네트워크는 항상 다른 스레드로 보냅니다.
- 목록 성능: 재사용과 지연 로딩이 핵심입니다. 항목마다 이미지 크기를 조절하지 않으면 스크롤이 가장 먼저 무너집니다.
- 메모리 누수: 화면이 사라졌는데 참조가 남아 회수되지 않는 상태입니다. 리스너와 콜백을 정리하지 않는 것이 대표적인 원인입니다.
- 이미지 메모리: 큰 이미지는 화면 크기에 맞춰 줄여서 올립니다. 원본 해상도를 그대로 올리면 몇 장으로도 메모리가 찹니다.
- 앱 크기: 다운로드 포기율에 직접 영향을 줍니다. 사용하지 않는 리소스와 중복 라이브러리가 대부분의 무게입니다.
- 배터리: 화면, 네트워크, 위치가 가장 많이 씁니다. 백그라운드에서 주기적으로 깨어나는 작업이 조용히 배터리를 태웁니다.
- 위치 정확도: 필요한 만큼만 정밀도를 요청합니다. 최고 정확도를 계속 켜 두면 배터리 소모가 눈에 띄게 늘어납니다.
- 백그라운드 작업: 시스템이 실행 시점을 조절하므로 정확한 시각을 보장하지 않습니다. 즉시성이 필요하면 푸시로 깨워야 합니다.
- 작업 병합: 여러 네트워크 요청을 모아 한 번에 보내면 무선 모듈이 깨어 있는 시간이 줄어듭니다. 개별 요청 최적화보다 효과가 큽니다.
- 프로파일링: 추측 대신 도구로 측정합니다. 실제 기기, 그중에서도 저사양 기기에서 재야 의미가 있습니다.
- 성능 예산: 시작 시간, 앱 크기, 프레임 저하율에 목표 숫자를 둡니다. 숫자가 없으면 성능은 항상 다음 순위로 밀립니다.
권한과 시스템 연동
- 권한 모델: 카메라, 위치, 알림, 연락처는 사용자 동의가 필요합니다. 거부당한 상태에서도 앱이 동작해야 합니다.
- 요청 시점: 그 기능을 쓰려는 순간에 요청하고 이유를 먼저 설명합니다. 시작하자마자 몰아서 요청하면 거부율이 크게 올라갑니다.
- 영구 거부: 사용자가 다시 묻지 않기를 선택하면 앱에서 다시 물을 수 없습니다. 설정으로 안내하는 경로를 준비해야 합니다.
- 알림 권한: 대체로 별도 동의가 필요하며 거부가 흔합니다. 알림에 의존하는 기능은 대안 경로를 함께 가져야 합니다.
- 푸시 알림: 서버가 기기를 깨워 메시지를 보냅니다. 토큰이 갱신되고 만료되므로 서버 쪽 정리 절차가 필요합니다.
- 알림 설계: 무엇을 언제 보낼지가 앱 삭제율에 직접 연결됩니다. 사용자가 종류별로 끌 수 있어야 전체를 끄지 않습니다.
- 딥링크와 앱 링크: 웹 주소로 앱의 특정 화면을 엽니다. 앱이 없을 때 웹으로 떨어지는 경로까지 설계해야 합니다.
- 공유와 인텐트: 다른 앱으로 내용을 보내고 받는 경로입니다. 시스템 표준을 쓰면 사용자가 이미 아는 방식이 그대로 통합니다.
- 백그라운드 위치: 별도의 강한 동의가 필요하고 심사에서 사용 근거를 요구합니다. 정말 필요한지 먼저 검토할 항목입니다.
- 카메라와 사진 접근: 전체 접근 대신 선택한 항목만 받는 방식이 있습니다. 최소 권한 원칙에 맞고 동의율도 높습니다.
- 결제: 디지털 재화는 대개 스토어 결제를 써야 하고 수수료와 심사 규칙이 따릅니다. 외부 결제 유도는 거절 사유가 되기 쉽습니다.
- 접근성 서비스: 화면 낭독과 확대를 지원하려면 요소마다 레이블과 역할이 필요합니다. 자동으로 되지 않고 명시해야 합니다.
- 시스템 설정 존중: 글자 크기, 다크 모드, 모션 감소는 앱이 아니라 사용자의 결정입니다. 무시하면 접근성 심사와 사용성 모두에서 걸립니다.
테스트
- 단위 테스트: 로직을 화면과 떼어 검증합니다. 화면 코드에 로직이 섞여 있으면 이 단계가 아예 불가능해집니다.
- 화면 테스트: 화면이 상태에 따라 무엇을 보여 주는지 확인합니다. 로딩과 오류 상태를 함께 검증해야 의미가 있습니다.
- 통합 테스트: 여러 층을 붙여 실제 흐름을 확인합니다. 느리므로 핵심 경로에만 씁니다.
- 종단 테스트: 실제 기기에서 사용자 시나리오를 자동으로 돌립니다. 불안정해지기 쉬워 재시도와 격리가 필요합니다.
- 테스트 더블: 네트워크와 저장소를 가짜로 바꿔 결과를 고정합니다. 의존성 주입이 되어 있어야 가능합니다.
- 화면 크기 테스트: 작은 기기, 태블릿, 분할 화면에서 각각 확인합니다. 개발 기기 하나로는 절대 드러나지 않습니다.
- 느린 네트워크 시험: 지연과 손실을 인위적으로 넣어 봅니다. 사무실 와이파이에서는 모든 앱이 잘 동작합니다.
- 저사양 기기: 성능 문제는 오래된 기기에서 먼저 드러납니다. 최신 기기에서만 확인하면 대다수 사용자의 경험을 모르는 것입니다.
- 크래시 재현: 로그와 스택만으로 부족하면 기기 상태와 순서를 함께 기록해야 합니다. 재현 불가 상태로 남는 버그가 가장 오래갑니다.
- 회귀 방지: 고친 버그에는 테스트를 붙입니다. 앱은 배포 주기가 길어 회귀 비용이 웹보다 큽니다.
- 베타 배포: 실제 사용자 일부에게 먼저 내보내 확인합니다. 스토어가 제공하는 경로를 쓰면 되돌리기도 쉽습니다.
- 접근성 검사: 화면 낭독으로 처음부터 끝까지 한 번 써 봅니다. 자동 검사가 잡지 못하는 문제가 대부분 여기서 나옵니다.
- 출시 전 점검: 권한, 딥링크, 결제, 로그아웃, 업데이트 경로를 매번 같은 목록으로 확인합니다. 기억에 의존하면 반드시 빠집니다.
배포와 운영
- 빌드 변형: 개발, 검증, 운영 빌드를 분리하고 서버 주소와 로그 수준을 다르게 둡니다. 하나로 쓰면 운영에 디버그 설정이 나갑니다.
- 서명: 앱은 서명 키로 신원을 증명합니다. 키를 잃으면 같은 앱으로 업데이트할 수 없으므로 보관이 곧 사업 연속성입니다.
- 버전과 빌드 번호: 사용자에게 보이는 버전과 스토어가 구분하는 번호는 다릅니다. 규칙을 정하지 않으면 어떤 빌드가 나갔는지 추적이 안 됩니다.
- 스토어 심사: 사람이 검토하며 거절 사유가 반복됩니다. 권한 설명, 로그인 없는 접근 경로, 결제 규칙이 흔한 지적입니다.
- 심사 지연: 배포는 언제나 예측 불가능한 대기를 포함합니다. 마감이 있는 기능일수록 여유를 크게 둬야 합니다.
- 단계적 출시: 일부 사용자에게 먼저 배포하고 지표를 보며 넓힙니다. 문제가 났을 때 영향 범위를 제한하는 가장 실용적인 장치입니다.
- 강제 업데이트: 특정 버전 미만을 막는 장치입니다. 서버 호환성이 깨질 때 필요하지만 남용하면 사용자를 잃습니다.
- 원격 설정: 배포 없이 값을 바꾸는 장치입니다. 앱은 되돌리기가 느리므로 웹보다 이 장치의 가치가 큽니다.
- 기능 플래그: 코드를 내보내되 켜는 시점을 분리합니다. 심사를 통과한 상태에서 공개 시점을 고를 수 있게 해 줍니다.
- 하위 호환: 옛 버전 앱이 오래 남아 있습니다. 서버 API는 상당 기간 두 버전을 동시에 지원해야 합니다.
- 크래시 수집: 스택과 기기 정보, 직전 사용자 동작을 함께 모읍니다. 크래시 없는 사용자 비율을 기준 지표로 삼습니다.
- 원격 로그와 분석: 화면에 접근할 수 없으므로 관측이 유일한 눈입니다. 개인정보를 남기지 않으면서 흐름을 알 수 있게 설계해야 합니다.
- 스토어 지표: 설치, 유지, 평점, 삭제율이 함께 움직입니다. 평점이 떨어지면 유입이 줄어 회복에 시간이 오래 걸립니다.
사용자 경험 특성
- 첫 실행: 앱을 처음 연 순간에 가치를 보여 줘야 합니다. 로그인부터 요구하면 대부분 여기서 이탈합니다.
- 로그인 없는 탐색: 계정 없이도 둘러볼 수 있게 하면 전환이 올라갑니다. 심사에서도 요구되는 경우가 있습니다.
- 오프라인 안내: 연결이 없을 때 무엇을 할 수 있는지 알려 줍니다. 빈 화면만 남기면 고장으로 읽힙니다.
- 낙관적 업데이트: 서버 응답 전에 화면을 먼저 바꿔 반응을 빠르게 만듭니다. 실패했을 때 되돌리는 규칙까지 있어야 성립합니다.
- 스켈레톤: 로딩 중 실제 레이아웃의 모양을 미리 보여 줍니다. 화면 이동이 줄어 체감 속도가 올라갑니다.
- 제스처: 스와이프와 길게 누르기는 발견되지 않습니다. 항상 눈에 보이는 대체 경로를 함께 둡니다.
- 터치 영역: 손가락으로 정확히 누를 수 있는 최소 크기가 있습니다. 아이콘이 작아도 누를 수 있는 범위는 크게 잡습니다.
- 한 손 조작: 큰 화면에서 위쪽은 닿지 않습니다. 주요 동작을 아래쪽에 두는 배치가 유리합니다.
- 입력 부담: 자동완성, 기본값, 형식 자동 변환으로 타이핑을 줄입니다. 모바일에서 입력은 웹보다 훨씬 비싼 행동입니다.
- 키보드 처리: 키보드가 올라올 때 입력창이 가려지지 않게 합니다. 가장 흔하고 가장 눈에 띄는 결함입니다.
- 중단 복구: 전화, 알림, 앱 전환으로 언제든 끊깁니다. 돌아왔을 때 하던 일이 그대로여야 합니다.
- 모션: 화면 전환에 방향을 주면 어디서 왔는지 알 수 있습니다. 과하면 느려 보이고 모션 감소 설정도 존중해야 합니다.
- 알림과 방해: 필요한 순간에만 보냅니다. 알림 하나가 앱 삭제로 이어지는 일이 실제로 자주 일어납니다.
개념들은 화면 하나를 만드는 동안 만납니다
주문 내역 목록 하나를 만드는 과정에도 이 지도의 거의 모든 영역이 들어옵니다.
- 화면 상태를 정의합니다. 로딩, 목록 있음, 비어 있음, 오류를 모두 표현할 수 있어야 화면이 완성됩니다.
- 데이터를 어디서 읽을지 정합니다. 로컬을 먼저 보여 주고 서버로 갱신할지, 서버만 볼지가 오프라인 경험을 갈라놓습니다.
- 목록을 나눠 받습니다. 커서 기반 페이지네이션과 재사용 가능한 항목 뷰가 스크롤 성능을 결정합니다.
- 이미지를 처리합니다. 화면 크기에 맞춰 줄이고 캐시하고 화면을 벗어나면 취소해야 메모리가 버팁니다.
- 네트워크 실패를 다룹니다. 타임아웃과 재시도를 걸고, 실패했을 때 다시 시도할 방법을 화면에 남깁니다.
- 생명주기를 붙입니다. 화면을 떠나면 요청을 취소하고, 프로세스가 죽었다 살아나면 스크롤 위치까지 복원합니다.
- 권한과 알림을 확인합니다. 배송 알림을 쓰려면 거부된 상태에서도 목록이 동작해야 합니다.
- 접근성을 검증합니다. 각 항목에 읽을 이름이 있고 터치 영역이 충분한지 화면 낭독으로 확인합니다.
- 배포를 준비합니다. 단계적 출시로 일부에게 먼저 내보내고 크래시 없는 사용자 비율을 지켜봅니다.
각 개념을 따로 배우는 이유는 화면 하나를 아홉 단계로 나눠 만들기 위해서가 아닙니다. 앱이 이상하게 동작할 때 원인이 상태 설계인지, 생명주기인지, 네트워크인지, 메모리인지 좁혀 가기 위해서입니다. 기기 문제라고 적는 순간 고칠 수 있는 것이 하나도 남지 않습니다.
처음 배운다면 이 순서가 좋습니다
- 생명주기부터 익힙니다. 화면이 언제 죽고 언제 살아나는지 직접 로그로 찍어 보면 앱과 웹의 차이가 몸에 붙습니다.
- 상태를 네 가지로 나눠 봅니다. 지금 만들고 있는 화면에 로딩, 성공, 비어 있음, 오류가 다 있는지 확인합니다.
- 비행기 모드로 써 봅니다. 오프라인에서 무엇이 깨지는지가 앱의 실제 완성도입니다.
- 저사양 기기에서 돌려 봅니다. 성능 문제는 최신 기기에서 절대 드러나지 않습니다.
- 권한을 거부해 봅니다. 거부한 상태에서 앱이 어떻게 되는지 확인하고 안내 경로를 만듭니다.
- 화면 낭독으로 한 번 씁니다. 접근성과 레이블 누락이 한꺼번에 드러납니다.
- 단계적으로 배포합니다. 되돌릴 수 있는 상태에서 내보내는 경험을 먼저 만듭니다.
이 순서가 절대적인 것은 아닙니다. 작은 앱 하나를 실제로 스토어까지 올려 보면서 필요한 개념을 앞뒤로 오가는 편이 훨씬 오래 남습니다.
이 문서는 시리즈의 허브입니다
이후의 심화 글은 각 문서만 읽어도 이해되도록 쓰고 mobile-core-concepts 태그로 연결합니다. 새 글이 발행되면 이 허브의 관련 항목에도 직접 링크를 추가합니다. 번호대로 읽어야 하는 연재물이 아니라, 관심 있는 지점에서 들어와 전체 지도로 돌아올 수 있는 구조입니다.
먼저 확장하기 좋은 주제는 다음과 같습니다.
- 앱이 죽었다 살아날 때: 상태 복원 설계
- 오프라인 우선: 로컬을 진실로 두고 동기화하기
- 목록이 버벅이는 진짜 이유: 재사용과 이미지 크기
- 권한 요청 시점이 동의율을 바꾼다
- 푸시 알림 토큰 수명 관리
- 인증서 고정을 걸 때 함께 준비할 것
- 단계적 출시와 강제 업데이트의 판단 기준
- 크래시 없는 사용자 비율을 기준 지표로 쓰기
플랫폼과 프레임워크는 계속 바뀌지만 물어야 할 질문은 크게 달라지지 않습니다. 이 화면은 언제 죽는가, 죽었다 살아나면 무엇이 남는가, 연결이 없을 때 무엇을 할 수 있는가, 이 작업이 배터리를 얼마나 쓰는가, 그리고 잘못 내보냈을 때 되돌릴 수 있는가. 이 다섯 질문을 기준으로 두면 처음 보는 도구도 이미 아는 개념 위에 놓고 이해할 수 있습니다.
함께 읽기
- 소프트웨어 아키텍처 핵심 개념 지도: 모듈 경계에서 이벤트 기반 시스템까지같은 기능을 만드는데 어떤 팀은 이틀에 끝내고 어떤 팀은 두 달을 씁니다. 실력 차이보다는 앞선 결정들이 무엇을 허용하고 무엇을 막아 놓았는지의 차이인 경우가 많습니다. 아키텍처는 화려한 다이어그램이 아니라, 나중에 바꾸기 어려운 결정들의 집합입니다.
- 웹 플랫폼 핵심 개념 지도: URL에서 렌더링과 보안까지웹 개발을 프레임워크 이름으로만 배우면 기술이 바뀔 때마다 지식도 함께 낡아 보입니다. 하지만 브라우저가 주소를 해석하고, 서버와 통신하고, 문서를 파싱하고, 픽셀을 그리는 기본 과정은 훨씬 천천히 바뀝니다. React, Vue, Svelte와 Next.js도 이 과정 위에서 서로 다른 개발 방식을 제공합니다.
- 클라우드와 DevOps 핵심 개념 지도: 인프라에서 배포와 관측성까지클라우드와 DevOps를 제품 목록으로 익히면 비슷한 기능을 가리키는 이름이 계속 늘어납니다. 가상 머신, 컨테이너, 서버리스, CI/CD와 Kubernetes는 같은 층의 대안이 아닙니다. 어떤 것은 실행 환경이고, 어떤 것은 배포 흐름이며, 어떤 것은 원하는 상태를 유지하는 제어 시스템입니다.
- 컴퓨터 공학 핵심 개념 지도: CPU에서 분산 시스템까지컴퓨터 공학을 처음 접하면 자료구조, 운영체제, 네트워크, 데이터베이스가 서로 다른 과목처럼 보입니다. 실제 시스템에서는 이 개념들이 한 요청 안에서 동시에 움직입니다. 사용자가 버튼을 누르면 프로그램의 명령어가 CPU에서 실행되고, 운영체제가 메모리와 소켓을 관리하며, 네트워크 패킷이 서버로 이동하고, 데이터베이스 트…
- 커널 패치는 왜 재부팅해야 적용될까? Livepatch 와 자동 재부팅새로 만든 서버를 점검하다가 이걸 봤습니다.