탐구

설치 없는 앱의 시대

작성: makemind · 2026년 1월 8일
이 글에는 실증본이 있습니다. 같은 주제를 돌아가는 코드와 실제로 그려진 화면으로 다시 만들었습니다 — 화면 층만 녹는다 — 설치 없는 앱, 그리고 컴파일이 얼려 둔 것. 이 글은 쓰인 그대로 둡니다.

버튼 색 하나 바꾸는 데 필요한 것들

기능 하나를 고쳤다고 해보자. 버튼 색을 바꾸고, 오타를 잡고, 잘못된 계산 로직 한 줄을 손봤다. 코드 변경량은 다섯 줄 남짓. 작업 자체는 십 분이면 끝난다.

그런데 그 십 분짜리 수정이 사용자의 화면에 도달하기까지 무슨 일이 벌어지는지 떠올려 보자.

먼저 빌드한다. 전체 앱을 다시 컴파일한다. 그다음 패키징하고 서명한다. 스토어에 올린다. 심사를 기다린다 — 운이 좋으면 하루, 보통은 이삼 일. 거절되면 사유를 읽고 고쳐서 다시 제출한다. 승인이 떨어지면 배포가 시작된다. 그리고 여기서 끝이 아니다. 사용자의 상당수는 한동안 옛 버전을 쓴다. 자동 업데이트를 꺼 둔 사람, 와이파이를 기다리는 사람, 업데이트 알림을 그냥 닫아 버린 사람. 당신이 고친 그 오타는, 빠르면 며칠 느리면 몇 주에 걸쳐 사용자에게 서서히 도달한다.

버튼 색 하나 바꾸는 데 이 모든 과정이 필요했다. 그리고 우리는 이것을 수십 년 동안 당연한 비용으로 받아들여 왔다. 모바일 앱이든 데스크톱 프로그램이든, "고쳤다"와 "사용자가 고쳐진 것을 본다" 사이에는 늘 이 긴 사슬이 있었다.

손안의 화면 — 우리가 매일 쥐고 쓰는 앱들, 그 뒤엔 늘 긴 사슬이 있었다
손안의 화면 — 우리가 매일 쥐고 쓰는 앱들, 그 뒤엔 늘 긴 사슬이 있었다

이 글은 그 사슬이 왜 존재하는지, 어떻게 우리가 거기에 갇혔는지, 그리고 그것이 필연이 아니었다는 것을 이야기한다. 긴 글이 될 것이다. 창간 Vol의 첫 글로서, 이 매거진이 선 자리를 분명히 해 두고 싶기 때문이다.

우리는 어떻게 이 사슬에 갇혔나

이 사슬이 처음부터 있었던 건 아니다. 짧게 계보를 짚어 보자. 지금의 답답함이 어디서 굳어졌는지 알면, 무엇을 풀어야 하는지도 분명해진다.

1세대 — 패키지 소프트웨어. 프로그램을 CD나 디스켓에 담아 팔던 시절. 화면도 로직도 전부 사용자의 컴퓨터에 설치됐다. 고치려면? 새 버전을 찍어 다시 배포하고, 사용자가 다시 설치해야 했다. 업데이트는 분기에 한 번, 운이 나쁘면 연 단위였다. 사슬의 원형이 여기서 생겼다 — 프로그램의 본체가 사용자 기기에 있다.

2세대 — 웹. 브라우저가 모든 것을 바꿨다. 화면을 서버가 내려 주고, 브라우저는 그것을 그릴 뿐이었다. 고치면? 다음 방문자는 즉시 새 화면을 본다. 설치도, 업데이트도 없었다. 사슬이 처음으로 끊긴 순간이었다. 우리는 자유로워졌다 — 문서를 다루는 한.

3세대 — 앱스토어. 스마트폰이 등장하자 흐름이 거꾸로 돌아갔다. 카메라, GPS, 푸시 알림, 가속도 센서, 오프라인 동작, 매끄러운 60프레임 애니메이션 — 웹이 주지 못하던 네이티브의 능력을 위해, 우리는 다시 기기에 설치되는 앱으로 돌아갔다. 그리고 이번엔 한 겹이 더 붙었다. 스토어라는 관문, 그리고 심사. 사슬이 1세대보다 길어진 채로 다시 굳었다.

여기서 핵심을 봐야 한다. 우리가 앱스토어 모델로 돌아간 이유는 네이티브의 능력 때문이었지, 설치·심사·업데이트라는 사슬을 원해서가 아니었다. 사슬은 능력을 얻기 위해 어쩔 수 없이 따라온 비용이었다. 그런데 우리는 어느새 그 비용을 능력과 한 묶음으로 여기게 됐다. "네이티브 능력을 원하면 사슬도 감수해야 한다"고.

이 글이 묻는 것은 바로 그 묶음이다.

능력과 사슬은 정말 분리될 수 없는가?

우리가 이미 시도해 온 우회들

업계가 이 사슬을 가만 견딘 것은 아니다. 사슬을 우회하려는 시도는 계속 있었고, 그 시도들의 성공과 한계를 보면 진짜 해법의 윤곽이 드러난다.

하이브리드 앱(웹뷰). 앱 껍데기 안에 브라우저를 넣고, 화면은 웹으로 그리는 방식. 화면을 서버에서 바꿀 수 있으니 사슬이 일부 끊겼다. 그러나 대가가 컸다 — 웹뷰는 네이티브만큼 매끄럽지 않았고, 기기의 깊은 기능에 닿기 어려웠으며, "웹 같은 앱"이라는 어정쩡한 느낌을 줬다. 능력을 일부 포기하고 즉시성을 산 셈이다.

코드 푸시(핫 업데이트). 심사를 거치지 않고 자바스크립트 번들을 기기에 밀어 넣어 앱 로직을 갱신하는 방식. 긴급 수정엔 유용했지만, 본질은 여전히 기기에 코드를 심는 것이었다. 스토어 정책과 줄다리기를 해야 했고, 큰 변경은 결국 정식 심사로 돌아가야 했다. 사슬을 끊은 게 아니라 느슨하게 했을 뿐이다.

서버 드리븐 UI(SDUI). 대형 서비스들이 조용히 써 온 방식. 화면의 구성(어떤 카드를, 어떤 순서로, 어떤 데이터로 보일지)을 서버가 내려 주고, 앱은 그 명세를 받아 네이티브 위젯으로 그린다. 피드, 홈 화면처럼 자주 바뀌는 영역에서 위력을 발휘했다. 이것이 가장 본질에 가까운 시도다 — 네이티브로 그리되, 무엇을 그릴지는 서버가 정한다.

그런데 SDUI에도 한계가 있었다. 대개 각 회사가 자기 서비스만을 위해 만든 폐쇄적 시스템이었다. 그 회사의 그 앱에서만 동작하는 명세, 그 회사 서버하고만 말하는 구조. 범용 표준이 아니었다. 그래서 "우리 피드 화면은 서버가 정의한다"는 됐어도, "아무 서버나 아무 기기에 화면과 도구를 정의해 보낸다"는 되지 못했다.

여기까지가 업계가 도달한 지점이다. 즉시성은 웹이, 능력은 네이티브가, 화면 동적 정의는 SDUI가 각각 보여 줬다. 다만 그 셋이 하나의 열린 표준으로 합쳐지지 않았을 뿐이다.

왜 앱은 "설치"되어야 했나 — 구조를 보다

이제 근본 질문으로 돌아가자. 너무 당연해서 아무도 묻지 않는 질문이다. 왜 앱은 사용자의 기기에 설치되어야 하는가?

답은 앱이 무엇으로 이루어졌는지를 보면 나온다. 앱은 두 가지다. 하나는 무엇을 보여줄지(화면, 레이아웃, 버튼의 위치와 색), 다른 하나는 무엇을 할지(버튼을 누르면 일어나는 일, 데이터를 다루는 규칙). 전통적인 앱은 이 둘을 모두 코드로 작성해 기기에 심어 둔다. 화면도 코드, 동작도 코드. 그 코드 뭉치를 컴파일한 결과물이 바로 "설치되는 앱"이다.

그래서 무언가 바뀌면 — 화면이든 동작이든 — 기기 안에 심어 둔 그 코드 뭉치를 통째로 갈아 끼워야 한다. 일부만 바꿀 방법이 마땅치 않다. 그것이 빌드·심사·설치·업데이트라는 사슬의 뿌리다. 사슬은 게으름이나 낡은 관행 때문에 있는 게 아니라, "앱의 본체가 기기 안에 있다"는 구조에서 필연적으로 나온 것이다.

이 구조에는 깊은 가정이 깔려 있다. 기기는 똑똑해야 한다. 화면을 어떻게 그릴지, 버튼을 누르면 뭘 할지, 다음에 뭘 보여줄지 — 그 모든 판단을 기기 안의 코드가 내려야 한다. 그래서 그 판단 코드를 전부 기기에 미리 넣어 두는 것이다.

그런데 — 이 가정을 뒤집으면 어떻게 될까?

전제를 뒤집기: 서버가 화면을 정의한다면

이렇게 상상해 보자. 화면과 동작을 기기가 아니라 서버가 정의한다. 기기는 더 이상 "무엇을 보여줄지"를 스스로 알지 못한다. 대신 서버에 묻는다 — "지금 이 화면에 뭘 그려야 해?" 서버가 "제목 하나, 그 아래 버튼 하나, 버튼을 누르면 이 동작"이라고 답하면, 기기는 그 지시대로 그릴 뿐이다.

이 작은 뒤집기가 사슬 전체를 무너뜨린다.

기기에는 더 이상 "이 앱만의 코드"가 없다. 기기에 있는 것은 무엇이 와도 그려 줄 수 있는 범용 그리기 엔진 하나뿐이다. 화면이 바뀌어야 하면? 서버의 정의를 고친다. 새 기능이 필요하면? 서버에 동작을 추가한다. 기기에는 손댈 게 없다. 빌드할 것도, 심사받을 것도, 설치하거나 업데이트할 것도 없다 — 기기 안에는 바꿀 "앱"이 애초에 없으니까.

앞 절에서 본 우회들과 무엇이 다른가. 하이브리드는 네이티브 능력을 포기했지만, 여기선 그리는 쪽이 진짜 네이티브 런타임이라 능력을 포기하지 않는다. 코드 푸시는 여전히 기기에 코드를 심었지만, 여기선 기기에 앱별 코드 자체가 없다. SDUI는 한 회사의 폐쇄 시스템이었지만, 여기서 지향하는 것은 열린 표준 — 아무 서버나, 약속된 방식으로 화면과 도구를 정의해 보내면, 아무 기기의 범용 런타임이 그것을 그린다.

이 "약속된 방식"이 핵심이다. 서버와 기기가 같은 언어로 말해야 한다. 무엇을 화면이라 부르고, 도구를 어떻게 호출하고, 데이터를 어떤 모양으로 주고받을지에 대한 공통 규약. 이 규약이 한 회사 안에 갇히지 않고 열려 있을 때, 비로소 "모든 서버가 앱이 될 수 있다"가 성립한다. (이 규약이 구체적으로 어떻게 생겼는지는 이 매거진의 코딩·프로토콜 연재에서 한 층씩 벗겨 나갈 것이다.)

한 장면

추상적으로 들릴 테니, 한 장면을 그려 보자.

서버에 이런 정의가 들어 있다고 하자 — "이 화면에는 환영 문구가 하나 있고, 그 아래 버튼이 하나 있다. 버튼을 누르면 주문 도구를 호출한다." 사용자가 앱을 열면, 기기는 이 정의를 받아 그대로 그린다. 문구와 버튼이 뜬다.

이제 당신이 서버에서 그 정의를 고친다. "버튼을 두 개로 만들고, 하나는 주문, 하나는 취소. 색은 파란색." 저장한다.

다음 순간, 사용자의 화면에 버튼이 두 개가 된다. 그들은 아무것도 하지 않았다. 업데이트를 누르지도, 앱을 다시 받지도, 스토어에 가지도 않았다. 당신은 빌드하지 않았고, 심사를 기다리지 않았고, 배포 버튼을 누르지 않았다. 서버의 정의 한 줄을 고쳤을 뿐이다.

십 분짜리 수정이 십 분 만에 모든 사용자에게 도달한다.

글머리에서 이야기한 그 긴 사슬이 — 통째로 사라진 자리다.

당연히 떠오르는 반론들

여기까지 읽은 기술자라면 머릿속에 여러 반론이 떠올랐을 것이다. 그 반론들에 정면으로 답하지 않으면 이 글은 공허한 선언에 그친다. 하나씩 짚자.

"서버가 화면을 정의하면, 오프라인에선 아무것도 못 하지 않나?" 타당한 우려다. 답은 — 화면 정의는 캐시된다. 한 번 받은 정의는 기기에 보관되고, 연결이 끊겨도 마지막 화면은 동작한다. 새 정의가 필요할 때만 서버에 묻는다. 웹이 오프라인 캐싱으로 PWA를 만든 것과 같은 원리이되, 네이티브 런타임 위에서다. "항상 연결돼야 한다"는 오해는, 매 순간 서버를 호출한다는 잘못된 그림에서 온다. 실제로는 정의가 바뀔 때만 오간다.

"매 화면을 서버에서 받으면 느리지 않나?" 화면 정의는 작다. 무거운 코드 번들이 아니라, "버튼 하나, 텍스트 하나"라는 가벼운 명세다. 그리고 위에서 말했듯 캐시된다. 정작 무거운 것 — 그리기 엔진 — 은 이미 기기에 네이티브로 있다. 사용자가 체감하는 성능은 네이티브 그대로다. 서버가 정의하는 것은 무엇을 그릴지이지, 그리는 행위 자체가 아니다.

"보안은? 서버가 화면과 동작을 내려 준다면, 악의적 정의를 내려보낼 수도 있지 않나?" 그래서 런타임은 받은 정의를 신뢰하지 않고 검증한다. 정의가 할 수 있는 일의 범위는 런타임이 정한 경계 안에 묶인다 — 임의 코드 실행이 아니라, 미리 정의된 위젯과 도구의 조합만 가능하다. 이것은 웹 브라우저가 임의 사이트의 자바스크립트를 샌드박스 안에서만 실행하는 것과 같은 발상이다. 서버가 "이런 화면을 그려라"라고는 해도, "기기의 모든 것을 마음대로 해라"라고는 못 한다.

"앱스토어 정책 위반 아닌가? 심사 없이 기능을 바꾸는 건데." 미묘한 영역이고, 정직하게 말해 경우에 따라 다르다. 스토어들은 "심사를 우회해 앱의 핵심 동작을 통째로 바꾸는" 것을 경계해 왔다. 그러나 "서버가 콘텐츠와 화면 구성을 정의하는" 것은 — 모든 피드, 모든 커머스 앱이 이미 하는 일이다. 경계는 임의 네이티브 코드를 심느냐에 있지, 화면을 서버가 정의하느냐에 있지 않다. 이 모델이 후자에 머무는 한, 기존 SDUI가 그랬듯 정책 안에 있다. (다만 이건 플랫폼 정책에 대한 해석이며, 법률·정책 자문이 아니다. 실제 적용 시엔 각 스토어의 최신 가이드라인을 확인해야 한다.)

"서버 비용과 의존성은?" 공짜는 없다. 화면 정의를 내려 주는 서버가 떠 있어야 한다. 다만 그 부담은 — 이미 거의 모든 앱이 백엔드를 갖고 있다는 점에서 — 새로 생기는 것이라기보다 역할이 커지는 것에 가깝다. 그리고 뒤에서 다루겠지만, 이 매거진이 다루는 생태계에서는 그 서버 자체가 곧 제품이 된다.

이 반론들에 답하고 나면, "설치 없는 앱"은 더 이상 마법이 아니라 공학적으로 설명되는 구조가 된다. 마법은 의심받아 마땅하지만, 구조는 검증될 수 있다.

무엇이 달라지는가

전제가 바뀌면 그 위에 서 있던 것들이 함께 바뀐다. 단지 "배포가 편해진다"가 아니다.

고치는 비용이 0에 가까워지면, 고치는 방식이 바뀐다. 심사에 사흘이 걸리고 사용자 절반이 옛 버전을 쓰는 세계에서는, 한 번 배포할 때 최대한 많은 걸 담아 신중하게 내보낸다. 실수하면 되돌리는 데 또 사흘이 걸리니까. 그러나 고침이 즉시 반영되고 즉시 되돌릴 수 있다면, 작게 자주 고치는 게 자연스러워진다. 화면 하나를 오늘 바꿔 보고, 반응이 안 좋으면 내일 되돌린다. 실험의 단위가 작아진다. 이것은 단순한 편의가 아니라 제품을 만드는 리듬 자체의 변화다.

누가 앱을 만들 수 있는가도 바뀐다. 빌드 환경을 갖추고, 서명 키를 관리하고, 스토어 계정을 운영하고, 심사 규칙을 익히는 일 — 이 모든 진입 장벽이 "앱을 만든다"는 행위에 붙어 있었다. 화면을 서버 정의로 그리는 세계에서는, 그 장벽의 상당 부분이 사라진다. 정의를 쓸 줄 알면 화면이 뜬다. 이것이 뜻하는 바는 크다. 개발 전문가가 아니어도 — 자기 도메인을 잘 아는 사람이 — 자기 도구를 만들 수 있게 된다. 변호사가 자기 상담 흐름을, 농부가 자기 재배 기록을, 공장 엔지니어가 자기 설비 제어 화면을. 이 매거진이 앞으로 줄곧 보여 줄 이야기가 바로 이것이다.

그리고 "앱"이라는 단어의 의미가 흐려진다. 기기에 설치되는 무거운 덩어리가 아니라, 서버가 정의하고 런타임이 그려 주는 살아 있는 화면이 된다. 그렇다면 서버 쪽에서 도구와 데이터와 화면을 정의할 수 있는 무언가가 있다면 — 그것은 이미 앱인 셈이다. 이 생각의 끝에 이 매거진이 거듭 다룰 명제가 있다. 모든 서버가 앱이 될 수 있다면? 그 함의는 이 글 한 편에 담기엔 너무 크다. 앞으로의 연재가 그것을 하나씩 풀어 갈 것이다.

그래서, 의심하라

여기까지 읽고 "그래도 정말 그게 될까" 싶다면 — 그 의심이 옳다. 글로 된 비전은 얼마든지 그럴듯하게 쓸 수 있다. 역사를 그럴듯하게 꿰고, 반론에 그럴듯하게 답할 수도 있다. 중요한 건 그게 실제로 동작하느냐다.

그래서 이 매거진은 비전을 길게 늘어놓는 데서 멈추지 않는다. 다음 글들에서 직접 만들어 보일 것이다. 설치 없이 화면 하나를 띄우는 것부터 시작해, 상태를 다루고, 서버의 도구를 호출하고, 끝내는 공장의 장비와 병원의 진료 흐름과 한 사람의 전문 지식이 앱이 되는 과정까지. 한 걸음씩, 코드와 함께, 실제로 돌아가는 것으로.

이 글이 던진 모든 주장은 — 사슬은 필연이 아니었고, 능력과 사슬은 분리될 수 있으며, 누구나 자기 도구를 만들 수 있다는 — 다음 연재들에서 증거로 갚을 약속이다.

마지막으로 하나만 남겨 두자. 당신이 마지막으로 휴대폰에서 "앱 업데이트"를 누른 것이 언제인가. 그 익숙한 행위가 — 사라지기 시작하고 있다.


makemind.dev 「탐구」 — 「설치 없는 앱」 Vol의 여는 글입니다. 다음 글 「10줄로 첫 화면을 띄우다」에서, 빌드도 설치도 없이 화면 하나를 띄우는 가장 짧은 길로 이어집니다.

Twitter