이 글에는 제휴 링크가 없습니다. 캐릭터 삽화는 GPT 이미지 생성으로 제작했고, 앱 화면은 직접 캡처했습니다.
HTML 파일 하나로 앱 만들기 — 설치도 서버도 없이 내가 쓸 앱을 갖는 가장 빠른 방법
“앱을 만든다”고 하면 앱스토어 등록, 서버, 개발자 고용이 떠오르죠. 그런데 저는 지금 실제로 쓰는 앱이 셋 있는데, 전부 HTML 파일 하나입니다. 19명 대가족 여행에 들고 간 앱, 이 사이트에 올려둔 API 비용 계산기, 그리고 이번 주에 만든 블로그 관제판. 셋 다 설치도 서버도 없이 더블클릭이면 열립니다.
이 글은 그 세 개를 근거로 왜 파일 하나로 되는지, 뭐가 되고 뭐가 안 되는지, 오늘 당장 하나 만드는 법을 정리합니다. 코딩을 몰라도 됩니다 — AI에게 시키는 프롬프트까지 같이 드려요.

결론 요약
- 브라우저가 곧 실행기라서, 화면(HTML)·모양(CSS)·동작(JS)을 한 파일에 담으면 그게 앱입니다
- 실물 3개 크기: 18KB · 5.8KB · 30KB — 사진을 파일 안에 넣으면 22MB까지도 갑니다
- 되는 것: 화면·버튼·계산·체크리스트·기기 저장·지도/전화 바로가기·오프라인. 안 되는 것: 여러 사람이 같은 데이터 공유, 알림, 비밀 보관
- 아래 40줄 템플릿을 메모장에 붙여넣고
.html로 저장하면 지금 바로 첫 앱이 생깁니다
🧩 1. 왜 파일 하나로 되나 — 브라우저가 실행기입니다
앱이 돌아가려면 “실행해주는 무언가”가 필요합니다. 폰 앱은 iOS·안드로이드가, PC 프로그램은 윈도우가 실행해주죠. HTML 파일은 브라우저가 실행해줍니다. 그리고 브라우저는 이미 모든 폰과 PC에 깔려 있어요.
HTML 파일 안에는 세 가지가 들어갑니다.
| 부분 | 역할 | 비유 |
|---|---|---|
| HTML | 화면에 뭐가 있는지 (제목, 목록, 버튼) | 뼈대 |
| CSS | 어떻게 보이는지 (색, 크기, 배치) | 옷 |
| JavaScript | 눌렀을 때 뭐가 일어나는지 (계산, 저장) | 근육 |
보통은 이 셋을 파일 여러 개로 나누지만, 한 파일에 다 넣어도 브라우저는 똑같이 읽습니다. 그래서 설치 과정도, 서버도, 인터넷 연결도 필요 없어요. 파일이 곧 앱입니다.
📦 2. 실물 3개 — 크기와 구조를 공개합니다
| 앱 | 용도 | 크기 | 안에 든 것 | 배운 것 |
|---|---|---|---|---|
| 여행 앱 v1 | 5가족 여행 일정 공유 | 18KB | 3일 일정, 맛집 5곳(전화·지도 바로가기), 준비물 체크리스트(기기 저장), 카톡 공유 버튼 | 기능은 완벽했는데 아무도 안 읽어서 폐기 |
| 여행 앱 최종 | 같은 용도, 지도로 재구성 | 22MB | 6탭 보물지도 포스터, 그림 속 번호 → 네이버지도 연결 | 이미지 6장을 파일 안에 넣으니 1,000배 커짐 — 그래도 읽혔음 |
| OpenAI 비용 계산기 | 사이트 무료 도구 | 5.8KB | 입력 4개, 계산 로직, 결과 표. 외부 라이브러리 0개 | 작은 계산기는 이 정도면 충분 |
| 블로그 관제판 | 발행 현황 한눈에 | 30KB | 표·배지·탭, 접힘 상태를 기기에 기억(localStorage). JS는 571자 | 30KB의 대부분(9.7KB)이 디자인(CSS) — 동작 코드는 놀랄 만큼 적음 |
세 가지가 보일 겁니다. 동작 코드는 생각보다 적고(관제판 JS 571자), 크기는 이미지가 결정하고(18KB→22MB), 실패는 기능이 아니라 가독성에서 옵니다(v1 폐기).
⚙️ 3. 되는 것과 안 되는 것 — 여기서 갈립니다
| 되는 것 ✅ | 안 되는 것 ❌ |
|---|---|
| 화면·버튼·탭·목록 | 여러 사람이 같은 데이터를 공유 (서버가 필요) |
| 계산기, 변환기, 체크리스트 | 푸시 알림 |
| 내 기기에 저장 (다음에 열어도 유지) | 앱스토어 등록 |
| 전화 걸기·지도 열기·카톡 공유 링크 | 비밀 보관 — 파일을 열면 코드가 다 보임 |
| 이미지·지도 그림 내장 | 수천 건 넘는 큰 데이터 |
| 인터넷 없이 실행 | 다른 기기와 자동 동기화 |
핵심은 왼쪽 열 세 번째, 내 기기에 저장입니다. 브라우저에는 localStorage라는 작은 저장 공간이 있어서, 체크한 항목이나 입력값을 파일 안에 기록해둘 수 있어요. 여행 앱의 준비물 체크리스트도, 관제판의 접힘 상태도 이걸로 기억합니다. 서버 없이 “앱답게” 느껴지는 건 대부분 이 기능 덕분이에요.
반대로 오른쪽 첫 줄 — 5가족이 같은 체크리스트를 같이 체크는 안 됩니다. 각자 자기 폰의 저장소에만 기록되니까요. 그게 필요해지는 순간이 서버가 필요해지는 순간이고, 그 전까지는 파일 하나로 충분합니다.
🎯 4. 오늘 만들기 — 40줄 복붙 템플릿
말로만 하면 안 믿기니까 진짜로 돌아가는 걸 드립니다. 여행 준비물 체크리스트 — 체크하면 줄이 그어지고, 항목을 추가할 수 있고, 닫았다 열어도 그대로 남습니다. 이 글을 쓰면서 브라우저에서 직접 열어 체크·추가·새로고침까지 확인했어요.

<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>여행 준비물</title>
<style>
body{font-family:sans-serif;max-width:480px;margin:24px auto;padding:0 16px}
h1{font-size:22px}
label{display:flex;gap:10px;align-items:center;padding:10px 0;border-bottom:1px solid #eee;font-size:17px}
input[type=checkbox]{width:22px;height:22px}
.done{color:#999;text-decoration:line-through}
#add{display:flex;gap:8px;margin-top:16px}
#add input{flex:1;font-size:16px;padding:8px}
button{font-size:16px;padding:8px 14px}
</style>
</head>
<body>
<h1>🧳 여행 준비물</h1>
<div id="list"></div>
<form id="add"><input placeholder="항목 추가" required><button>추가</button></form>
<script>
const KEY = 'trip-checklist';
let items = JSON.parse(localStorage.getItem(KEY) || 'null') || [
{t:'구명조끼', d:false}, {t:'우비·방수팩', d:false}, {t:'상비약', d:false}];
const list = document.getElementById('list');
function save(){ localStorage.setItem(KEY, JSON.stringify(items)); }
function render(){
list.innerHTML = '';
items.forEach(it => {
const l = document.createElement('label');
l.className = it.d ? 'done' : '';
const c = document.createElement('input'); c.type = 'checkbox'; c.checked = it.d;
c.onchange = () => { it.d = c.checked; save(); render(); };
l.append(c, it.t); list.append(l);
});
}
document.getElementById('add').onsubmit = e => {
e.preventDefault(); const inp = e.target.querySelector('input');
items.push({t: inp.value.trim(), d:false}); inp.value = ''; save(); render();
};
render();
</script>
</body>
</html>
실행하는 법 — 3단계
- 위 내용을 전부 복사해 메모장에 붙여넣고, 파일 이름을
checklist.html로 저장 (저장할 때 “모든 파일” 선택, 인코딩 UTF-8) - 저장된 파일을 더블클릭 — 브라우저가 열리면 끝. 이게 앱입니다
- 폰에서 쓰려면: 파일을 카톡 ‘나와의 채팅’이나 이메일로 보내 열거나, 확실하게는 GitHub Pages 같은 무료 호스팅에 올려 링크로 씁니다 — 위 비용 계산기가 이 방식이에요
첫 줄의 구명조끼, 우비·방수팩, 상비약을 바꾸면 내 목록이 되고, 여행 준비물을 바꾸면 제목이 바뀝니다. 이 두 군데만 고쳐도 이미 “내 앱”이에요.
🤖 5. AI에게 시키기 — 프롬프트 한 장
직접 고치는 게 귀찮으면 AI에게 시키면 됩니다. 여행 앱 두 개를 Codex로 만들면서 배운 조건을 프롬프트로 굳혔어요. 이대로 복사해서 쓰세요.
HTML 파일 하나로 [무엇: 예) 우리 가족 주간 식단표] 앱을 만들어줘.
조건:
· 외부 라이브러리 없이, 파일 하나에 HTML·CSS·JS 전부
· 폰 화면(세로) 기준으로 큼직하게
· 입력한 내용은 localStorage에 저장해서 다시 열어도 유지
· 이 앱을 쓸 사람: [누가: 예) 요리 안 하는 남편, 초등학생 아이]
· 화면은 글자 나열 말고 [형태: 예) 요일별 카드 7장]으로
· 완성된 파일 전체를 코드블록 하나로 줘
마지막 두 줄이 핵심입니다. 여행 앱 v1이 폐기된 이유는 기능이 아니라 “누가 볼 물건인지”를 안 적어서였어요. “초등학생 10명도 들여다볼 것”이라고 바꾸는 순간 결과가 달라졌습니다. 기능 목록보다 소비 맥락을 적으세요.
받은 코드가 안 돌아가면 그대로 다시 붙여넣고 “이 파일을 열었더니 [증상]이 나와. 고쳐줘”라고 하면 됩니다 — 바이브 코딩의 기본 루프예요.
⚠️ 6. 주의 — 파일 하나라서 생기는 함정
- 파일 안에 비밀을 넣지 마세요. API 키, 비밀번호, 개인정보 — HTML 파일은 열면 코드가 그대로 보입니다. 비용 계산기가 API 키 없이 요금표만 넣은 이유예요
- 이미지를 넣으면 급격히 커집니다. 여행 앱은 그림 6장에 18KB → 22MB. 카톡으로 보내긴 부담스러운 크기였어요. 사진이 많으면 링크로 대체하거나 호스팅으로
- 브라우저 데이터를 지우면 저장한 것도 사라집니다. localStorage는 브라우저 안에 있어서, “방문 기록 삭제”를 하면 같이 날아가요. 오래 둘 데이터는 내보내기 버튼을 달거나 별도 백업을
- 여러 명이 같이 편집해야 하면 이 방식이 아닙니다. 그건 서버가 필요한 일이고, 그때 가서 고민해도 늦지 않아요
마무리 — “앱을 만들었다”의 문턱
AI 업무 자동화는 도구가 아니라 순서라고 썼는데, HTML 파일 하나는 그 순서의 첫 번째 실물입니다. 계산기 하나, 체크리스트 하나가 “내가 쓰는 앱”이 되는 순간 AI에게 뭘 시킬 수 있는지에 대한 감이 완전히 달라져요. 위 템플릿을 저장하고 항목 하나만 바꿔보세요. 그게 시작입니다.
기준: 2026-09-08. 크기·구조는 이 저장소의 실제 파일(여행 앱 v1 18,990바이트, 최종 22,780,441바이트, 계산기 5,816바이트, 관제판 29,812바이트)을 직접 측정했습니다. 템플릿은 Edge에서 열어 체크·추가·새로고침 유지를 확인했습니다. 캐릭터 삽화는 GPT 이미지 생성, 앱 화면은 직접 캡처입니다.