15장. 인프라 담당 — 설정 파일을 기준으로 삼는다

이 장이 끝나면: 온티켓 코드가 GitHub 저장소에 올라가 있고(시크릿은 하나도 없이), API 서버의 배포 설정(wrangler.toml)과 프론트의 배포 준비(Vercel 연결)가 설정 파일로 갖춰져 있다. 이 모든 인프라 작업을 손이 아니라 프롬프트로 처리한다 — 사람의 일은 로그인과 승인이다.


15.1 개념 — 인프라의 제1원칙

인프라 담당은 무엇을 하는 자리인가

인프라는 서비스가 돌아가는 기반 전부를 말한다 — 코드가 보관되는 저장소, 배포되는 클라우드, 환경변수와 시크릿, 도메인. 개발자가 '만드는' 사람이라면 인프라 담당은 '돌아가게 하고, 계속 돌아가게 하는' 사람이다.

'인프라(infrastructure)'라는 말부터 풀어 두자. infra는 라틴어로 '아래'라는 뜻이고, structure는 '구조물'이다. 합치면 '아래에서 떠받치는 구조물' — 도시로 치면 도로·상하수도· 전기·통신망이다. 사람들은 평소 도로를 의식하지 않는다. 그러나 도로가 끊기면 도시 전체가 멈춘다. 소프트웨어의 인프라도 똑같다. 잘 돌아갈 때는 아무도 눈치채지 못하지만, 서버가 죽거나 배포가 꼬이면 서비스 전체가 멈춘다. 온티켓으로 치면, 우리가 지금까지 만든 예매·결제· QR 기능이 아무리 훌륭해도 그것이 내 노트북 안에서만 돌아간다면 아무도 티켓을 살 수 없다. 인프라 담당의 일은 이 코드가 세상의 어딘가에서 24시간 돌아가게 만드는 것이다.

지금까지 우리는 '만드는' 자리들을 거쳐 왔다 — 기획, 백엔드, 프론트, 디자인, 검증. 이제 자리가 하나 바뀐다. 만든 것을 세상에 내보내고, 계속 서 있게 하는 자리다. 성격이 사뭇 다르다. 만드는 일은 새 기능을 더하는 일이라 실수해도 대개 되돌리기 쉽다. 그러나 인프라는 '되돌리기 어려운 행동'이 유난히 많다 — 코드를 세상에 공개하고, 클라우드에 배포하고, 도메인을 연결하는 일들이 그렇다. 그래서 이 자리는 신중함을 기술의 핵심으로 삼는다.

[짚고 가기] 앞선 장들을 지나오며 "AI에게 맡기고 승인만 하면 된다"는 리듬에 익숙해졌을 것이다. 이 장에서 그 리듬은 유지되지만, 승인의 무게가 달라진다는 점을 알아 두면 좋다. 지금까지의 승인은 대개 내 컴퓨터 안의 일이었다. 하지만 이 장부터는 승인 한 번이 코드를 세상에 공개하는 일일 수 있다 — 그래서 이 장에서는 퍼미션을 한층 진지하게 읽게 된다.

제1원칙: 설정 파일을 기준으로 삼는다

인프라 운영에는 오래전부터 골칫거리인 문제가 있다. 서버 하나를 콘솔(웹 관리 화면)에서 이것저것 클릭해 가며 손봐 왔다. 잘 돌아간다. 그런데 그 서버가 죽으면? 똑같이 만들 방법이 없다 — 무엇을 어떻게 눌렀는지 아무 데도 남아 있지 않기 때문이다. 이런 서버를 눈송이(snowflake)라고 부른다. 같은 것이 세상에 둘 없어서.

이 악몽을 조금 더 구체적으로 그려 보자. 어떤 회사의 결제 서버가 3년째 잘 돌아가고 있다. 그동안 담당자가 바뀔 때마다 누군가 콘솔에 들어가 설정을 조금씩 손봤다. "여기 타임아웃을 30초로", "저기 메모리를 2GB로", "이 방화벽 규칙 하나 추가". 각각은 작은 클릭이었고, 아무도 기록해 두지 않았다. 3년치의 클릭이 쌓여 지금의 서버가 되었다. 그러던 어느 날 이 서버가 하드웨어 고장으로 죽는다. 팀은 똑같은 서버를 다시 만들어야 한다. 그런데 아무도 그 3년치 클릭을 재현할 수 없다. 무엇을 눌렀는지 기억하는 사람이 없고, 어디에도 적혀 있지 않기 때문이다. 서비스는 며칠씩 멈추고, 팀은 설정을 하나씩 추측으로 복원한다. 이것이 눈송이 서버가 부르는 재해다.

'눈송이'라는 비유가 왜 딱 맞는지 음미해 두자. 눈송이는 하나하나가 다 다르게 생겼고, 손에 닿으면 녹아 없어진다. 두 번 다시 똑같은 것을 만들 수 없다. 손으로 클릭해 만든 서버가 정확히 그렇다 — 세상에 단 하나뿐이고, 죽으면 복제할 수 없다. 반대말은 '가축(cattle)'이라는 비유를 쓴다. 눈송이 서버는 이름을 붙여 애지중지 키우는 '애완동물(pet)'이고, 코드로 찍어 내는 서버는 언제든 똑같이 다시 만들 수 있는 '가축'이다. 한 마리가 죽어도 파일로 새 한 마리를 똑같이 찍어 낸다. 인프라 담당의 목표는 모든 서버를 애완동물이 아니라 가축으로 다루는 것이다.

그래서 현대 인프라의 표준은 IaC(Infrastructure as Code, 코드형 인프라) — 인프라의 모든 설정을 파일로 적고, 그 파일로부터 실제 인프라를 만들어 내는 방식이다. 원칙은 한 문장이다.

설정 파일을 기준으로 삼는다. 콘솔에서 직접 바꾸지 않는다.

파일을 기준으로 삼으면 세 가지가 따라온다.

이 셋을 하나씩 더 풀어 보자. 왜 이것이 그렇게까지 중요한지 감이 와야 원칙을 몸에 붙일 수 있다.

콘솔 클릭은 이 셋 모두를 잃는다. (콘솔은 '보는 용도'로 쓴다 — Supabase 대시보드에서 데이터를 눈으로 확인했듯이. 바꾸는 것은 파일과 명령으로.)

용어를 하나 더 잡아 두자. IaC를 우리말로 '코드형 인프라'라고 옮겼는데, 여기서 '코드'는 프로그래밍 언어로 짠 프로그램만을 뜻하지 않는다. 인프라를 서술하는 설정 파일 전부를 가리킨다. 우리가 이 장에서 만들 wrangler.toml, 이미 만들어 둔 .gitignore, .env.example — 이런 것들이 다 IaC의 일부다. 요점은 "인프라의 상태를 사람의 기억이나 콘솔의 클릭이 아니라, 읽고·복제하고·기록할 수 있는 파일로 붙잡아 둔다"는 발상이다.

[짚고 가기] "설정 파일을 기준으로 삼는다"는 이 장 전체를 관통하는 한 문장이다. 크게 적어 두고 절마다 되돌아오면 좋다. 나중에 "콘솔에서 그냥 바꾸면 안 되나요?"라는 생각이 들면, 스스로에게 되물어 보자 — "그러면 재현·기록·검토 중 무엇을 잃지?" 이 세 단어를 직접 떠올려 보면 원칙이 각인된다. 재해 복구를 겪어 본 사람이라면 눈송이 서버 이야기가 남 일 같지 않을 것이다.

인프라도 프롬프트로

과거에 인프라는 전문가의 성역이었다 — 명령어와 설정 문법을 아는 사람만 만질 수 있었다. 이제 다르다. 설정 파일 작성도, CLI 명령 실행도 AI가 한다. 사람에게 남는 일은 두 가지다: 계정에 로그인해 주는 것(권한은 사람의 것이므로), 그리고 설정과 명령을 승인하는 것. 이 장 전체가 그 분업의 연습이다.

이 분업이 왜 이렇게 나뉘는지 이해하면 이 장의 실습이 전부 자연스러워진다. 핵심은 "AI에게 넘길 수 있는 것과 넘길 수 없는 것의 경계" 다.

비유하자면 이렇다. AI는 인프라의 모든 문법과 절차를 아는 유능한 실무자다. 하지만 회사 금고의 열쇠는 사람이 쥐고 있다. 실무자가 "금고에서 이것을 꺼내 저기에 쓰겠습니다"라고 설명하면, 사람이 그 설명을 읽고 금고를 열어 준다. 열쇠(로그인)와 최종 허락(승인)은 사람의 것이고, 나머지 전문 노동은 실무자의 것이다. 이 장의 모든 실습이 이 구도를 따른다.

한 가지 오해를 미리 풀어 두자. "AI가 인프라를 다 한다"는 말이 "사람이 인프라를 몰라도 된다"는 뜻은 아니다. 오히려 반대다. AI가 만든 설정 파일을 사람이 읽고 판단해야 하기 때문에, 각 항목이 무슨 뜻인지는 알아야 한다. 다만 그 지식은 '외워서 타이핑하는' 지식이 아니라 '읽고 이해하는' 지식이다. 백지에서 wrangler.toml을 직접 쓸 줄은 몰라도 되지만, AI가 써 준 wrangler.toml을 읽고 "이 줄이 왜 있지?"를 물을 줄은 알아야 한다. 이 장은 그 '읽는 눈'을 기르는 장이기도 하다.

[짚고 가기] "그럼 인프라 공부는 안 해도 되나요?"라는 의문이 자연스럽게 든다. 위 오해 해소가 그대로 답이다 — 타이핑하는 지식에서 읽고 판단하는 지식으로 바뀐 것이지 지식이 필요 없어진 게 아니다. 이 구분을 흐릿하게 두면, 승인 창을 읽지 않고 엔터만 치는 습관으로 흐르기 쉽다. 이 장은 그 습관이 가장 위험해지는 장이다.

이 원칙은 회사 밖에서도 통한다

"머릿속이 아니라 문서가 기준"은 인프라만의 이야기가 아니다. 가게의 오픈·마감 절차가 사장 머릿속에만 있으면 사장이 아프면 가게가 멈춘다. 절차서(파일)를 기준으로 삼으면 누구든 그대로 연다. 경리의 엑셀 수식이 "그분만 아는 것"이면 퇴사가 재해가 된다. IaC는 이 상식을 인프라에 적용한 것뿐이다.

같은 상식을 몇 장면 더 늘어놓아 보면 원리가 또렷해진다.

이 장면들의 공통점은 하나다 — 지식이 사람의 머릿속(휘발성)에 있느냐, 파일(영속성)에 있느냐. 머릿속에 있으면 그 사람에게 의존하게 되고, 그 사람이 사라지면 지식도 사라진다. 파일에 있으면 누구든 재현할 수 있고, 시간이 지나도 남는다. IaC는 이 오래된 지혜를 인프라에 적용한 것뿐이다. 그래서 이 장에서 배우는 사고방식은 인프라를 떠나 여러분의 일 어디에나 쓰인다 — 업무 매뉴얼을 쓰는 일, 인수인계 문서를 남기는 일, 반복 작업을 자동화 스크립트로 붙잡아 두는 일. 전부 "머릿속을 파일로 옮기는" 같은 원리다.


15.2 용어 정리

이 장에서 처음 만나는(또는 다시 만나는) 용어들이다. 인프라는 낯선 이름이 많이 나오는 영역이지만, 완벽히 외울 필요는 없다. "이런 게 있고 무슨 역할이구나" 정도로 눈에 익혀 두면 실습하며 손에 붙는다.

저장소(repository)와 GitHub

저장소는 프로젝트의 모든 파일과 변경 이력을 담는 단위다. 지금까지 onticket 폴더가 내 컴퓨터 안의 저장소였다면, GitHub는 그 저장소를 올려 두는 클라우드 보관소다. 올려 두면 세 가지가 생긴다 — 백업(노트북이 죽어도 코드는 산다), 공유(팀·AI 도구들이 같은 코드를 본다), 그리고 배포의 출발점(클라우드 서비스들이 GitHub 저장소를 바라보며 배포한다). 코드를 올리는 행위를 push(푸시) 라고 한다. (브랜치·커밋 같은 Git의 본격적인 사용법은 검증 자동화와 함께 다룬다 — 지금은 "이력이 남는 보관소에 올린다"로 충분하다.)

용어를 더 풀어 두자. 'repository'는 원래 '무언가를 보관하는 장소'라는 뜻이다. 도서관을 '책의 repository'라고 부르듯, 코드 저장소는 '코드와 그 역사의 repository'다. 줄여서 repo(레포) 라고도 흔히 부른다. 강의 중 "레포"라는 말이 나오면 저장소를 가리킨다고 알아 두면 된다. 그리고 보통 저장소는 단순히 파일 묶음이 아니라 파일의 모든 버전을 담는다는 점이 핵심이다. 오늘 고친 파일의 어제 버전, 지난주 버전이 다 안에 남아 있어서, 언제든 과거로 되돌아갈 수 있다. 이 '시간 여행' 능력이 저장소를 단순한 클라우드 폴더(구글 드라이브 같은)와 구별 짓는 지점이다.

GitHub를 조금 더 소개해 두자. GitHub는 세계에서 가장 큰 코드 저장소 호스팅 서비스로, 수억 개의 프로젝트가 여기에 저장돼 있다. 이름의 'Git'은 저장소를 관리하는 기술(버전 관리 도구 Git)에서 왔고, 'Hub'는 그것들이 모이는 중심지라는 뜻이다. 개인·회사의 코드가 여기 모여 있어서, 오늘날 개발자에게 GitHub 계정은 명함이자 이력서 역할까지 한다. 비슷한 서비스로 GitLab, Bitbucket도 있지만, AI 개발 도구·클라우드 배포 서비스들이 가장 폭넓게 지원하는 것이 GitHub라 우리도 GitHub를 쓴다. 개인·비공개 저장소는 무료로 얼마든지 만들 수 있다.

'push'라는 말도 감을 잡아 두자. push는 '밀어 넣다'라는 뜻으로, 내 컴퓨터의 코드를 GitHub 쪽으로 밀어 올린다는 이미지다. 반대로 GitHub의 코드를 내 컴퓨터로 끌어내리는 것은 pull(풀) 이라고 부른다. 오늘 우리가 하는 일은 내 노트북의 온티켓 코드를 GitHub로 처음 밀어 올리는 것, 즉 첫 push다.

여기서 왜 push가 '되돌리기 어려운 행동'인지 미리 이해해 두자. 저장소는 이력을 남기는 보관소라고 했다. 그 말은, 한 번 올린 것은 이력에 남는다는 뜻이다. 실수로 시크릿이 담긴 파일을 올렸다가 다음 커밋에서 지워도, 이력을 뒤지면 그 파일이 있던 과거 버전이 남아 있다. 마치 지운 낙서 자국이 종이에 희미하게 남듯이. 그래서 "일단 올리고 나중에 지우면 되지"가 통하지 않는다 — 특히 시크릿은. 이것이 뒤의 '프롬프트 작성법'에서 배울 '올리기 전 전수조사'가 왜 절차인지의 이유다.

[짚고 가기] "구글 드라이브에 올리는 거랑 뭐가 달라요?"라는 물음이 좋은 출발점이 된다. 구글 드라이브는 최신 파일만 보관하지만, 저장소는 모든 버전의 역사를 보관한다. 그리고 그 역사가 있기에 "잘못 올린 시크릿이 과거 이력에 남는다"는 위험도 함께 온다. 이 두 얼굴(강력한 역사 관리 vs 지워지지 않는 흔적)을 같이 기억해 두면, 뒤의 전수조사 실습이 왜 중요한지 스스로 납득하게 된다.

CLI 3종 — 오늘의 도구

CLI 무엇을 조작하나 오늘 하는 일
gh GitHub 저장소 생성, push
wrangler Cloudflare Workers API 서버 배포 설정·배포
vercel Vercel 프론트 배포 연결

셋 다 "웹사이트에서 클릭으로 할 일을 명령으로 하는" 도구다. 명령이 되는 순간 AI가 실행할 수 있게 된다 — 우리가 CLI를 쓰는 진짜 이유다.

CLI가 무엇인지는 앞에서 이미 다뤘지만, 이 장에서 특히 중요하니 한 번 더 붙잡아 두자. CLI(Command Line Interface) 는 마우스 클릭이 아니라 글자 명령으로 조작하는 도구다. 같은 일을 하는 웹 화면(GUI)이 있는데도 왜 굳이 CLI를 쓰는가? 이유는 딱 하나, 글자 명령은 AI가 그대로 실행할 수 있기 때문이다. "GitHub 웹사이트에 들어가 New 버튼을 누르고 저장소 이름을 입력하고…"는 사람이 마우스로 해야 하지만, gh repo create onticket --private 라는 한 줄은 AI가 실행할 수 있다. 인프라를 프롬프트로 다루는 이 장의 모든 마법이 여기서 나온다 — 인프라 작업이 '명령'이 되는 순간, AI가 대신 실행할 수 있게 된다.

세 도구를 하나씩 소개해 두자. 이름과 정체를 알면 실습 중 명령이 지나갈 때 "아, 저건 GitHub를 조작하는 거구나" 하고 따라갈 수 있다.

CLI 도구들에 공통으로 있는 습관 하나를 알아 두면 편하다. 대부분의 CLI는 처음 쓸 때 로그인(auth/login) 명령으로 "나는 이 계정의 사람이다"를 증명하는 단계를 거친다. 이 로그인은 대개 브라우저를 열어 승인 버튼을 누르는 방식이다 — 우리가 첫날 Claude Code를 설치하며 로그인하던 것과 똑같은 흐름이다. 이 "브라우저로 로그인해서 도구에 권한을 연결"하는 패턴은 이 장에서 gh·wrangler·vercel 세 번 반복되니, 한 번 익히면 나머지는 같다.

[짚고 가기] 세 도구 이름을 처음 보면 "wrangler? 이런 걸 다 외워야 하나?" 싶어 위축되기 쉽다. 하지만 안심해도 된다 — 외우는 게 아니라 AI가 실행하고, 우리는 지나가는 명령을 읽기만 하면 된다. 다만 '무엇을 조작하는 도구인지'만 알면 승인 창을 읽을 때 맥락이 잡힌다. 위 표의 3열(무엇을 조작하나)만 눈에 익혀 두면 충분하다.

wrangler.toml — API 서버의 신분증명서

api/ 폴더에 두는 Workers 배포 설정 파일이다. 이 앱의 이름은 무엇이고, 어떤 파일이 진입점이며, 어떤 설정으로 배포되는지가 적힌다. 파일을 읽을 줄만 알면 된다 — "아, 이 파일이 배포될 모습의 설계서구나."

파일 이름부터 뜯어 보자. wrangler.toml은 두 부분이다. 앞의 wrangler는 이 파일을 읽는 도구가 wrangler라는 뜻이고, 뒤의 .toml은 파일 형식이다. TOML(Tom's Obvious, Minimal Language) 은 설정을 적기 위한 간단한 파일 형식으로, 사람이 읽기 쉽게 만든 것이 특징이다. 이름 = 값 꼴로 한 줄씩 적어서, 프로그래밍을 몰라도 대충 읽힌다. 우리가 이미 본 .env도 비슷한 이름=값 형식이었다. TOML은 거기에 구조(묶음)를 더한 버전이라고 보면 된다. 이런 설정 파일 형식으로는 TOML 외에 JSON·YAML도 흔한데, 각 도구가 선호하는 형식이 정해져 있어서 우리는 그저 wrangler가 쓰는 TOML을 따를 뿐이다.

'신분증명서'라는 비유가 왜 적절한지 보자. 사람의 신분증에는 이름·생년월일·주소가 적혀 있어서 "이 사람이 누구인지"를 증명한다. wrangler.toml에는 이 앱의 이름·진입점·호환성 설정이 적혀 있어서 "이 앱이 무엇이고 어떻게 배포되는지"를 규정한다. 클라우드는 이 파일을 읽고 그대로 앱을 배포한다. 그래서 이 파일이 곧 앞서 말한 '설계서'이자 IaC의 실체다 — 우리 API 서버라는 인프라의 상태가 이 파일 한 장에 붙잡혀 있는 것이다.

파일 안에 실제로 어떤 항목이 담기는지, 대표적인 것 몇 개만 미리 눈에 익혀 두자. (실습에서 AI가 각 줄에 주석으로 설명을 달아 줄 것이므로, 지금은 "이런 게 들어가는구나" 정도면 된다.)

항목 비유
name 이 앱의 이름 (예: onticket-api) 신분증의 이름
main 진입점 — 앱이 시작되는 파일 건물의 정문
compatibility_date 어느 시점의 Workers 동작 규칙을 따를지 "몇 년형 규격으로 지을지"

compatibility_date(호환성 날짜)만 조금 설명이 필요하다. 클라우드 플랫폼은 시간이 지나며 내부 동작 방식을 조금씩 바꾸는데, 어느 날 갑자기 바뀌면 기존 앱이 깨질 수 있다. 그래서 "이 앱은 이 날짜 시점의 규칙을 기준으로 동작해라"를 못 박아 두는 것이 이 항목이다. 자동차로 치면 "몇 년형 안전 규격으로 만든 차인지"를 적어 두는 셈이다. 이렇게 해 두면 플랫폼이 나중에 규칙을 바꿔도 우리 앱은 명시한 날짜의 규칙대로 안정적으로 돌아간다. 이런 작은 항목 하나에도 '재현 가능성'을 지키려는 IaC의 정신이 배어 있다.

[짚고 가기] wrangler.toml을 열고 겁먹지 않는 것이 이 절의 목표다. 이건 코드가 아니라 양식(서식)이라고 보면 된다 — 빈칸에 값이 채워진 신청서라고 생각하면 마음이 편하다. 파일을 열어 보면 줄 수가 열 줄 안팎이라 부담이 확 준다. 실습 4에서 각 줄을 소리 내어 읽으며 "이건 이름, 이건 정문…"이라고 짚어 보면 좋다.

환경변수를 관리하는 세 곳

환경변수는 이제 여러 곳에 존재하게 된다. 혼동하기 쉬우니 표로 박아 두자.

위치 파일/화면 언제 쓰이나 저장소에 올라가나
내 컴퓨터 .env 로컬 개발 서버 절대 안 올라간다 (훅이 지킨다)
클라우드 배포 서비스의 시크릿 설정 배포된 서비스 애초에 파일이 아니다
견본 .env.example "무엇이 필요한지" 목록 올라간다 (값이 없으니까)

같은 이름(DATABASE_URL)의 변수가 로컬에서는 .env에서, 클라우드에서는 그쪽 금고에서 공급된다. 코드는 어느 쪽인지 모른다 — 그래서 코드 수정 없이 환경을 오갈 수 있다.

이 표가 이 장에서 가장 헷갈리기 쉬운 부분이라, 천천히 세 곳으로 나눠 보자. 먼저 '환경변수' 자체를 다시 붙잡자. 환경변수는 코드 바깥에 두는, 환경마다 달라지는 값이다. 예를 들어 데이터베이스 주소(DATABASE_URL)나 결제 키는, 내 노트북에서 개발할 때와 진짜 서비스로 배포됐을 때 값이 다르다. 이런 값을 코드에 직접 박으면 두 가지가 곤란하다 — (1) 환경이 바뀔 때마다 코드를 고쳐야 하고, (2) 시크릿이 코드에 섞여 저장소에 올라가 버린다. 그래서 이런 값은 코드 바깥, 즉 '환경'에 두고, 코드는 이름표(DATABASE_URL)로만 불러다 쓴다.

이제 그 값을 관리하는 세 곳을 살펴보자.

세 곳의 역할을 한 문장으로 정리하면 이렇다 — 진짜 값은 저장소 밖(내 .env와 클라우드 금고)에 살고, 저장소에는 값이 빠진 견본(.env.example)만 올라간다. 이 규칙 하나가 "시크릿은 저장소 밖" 원칙의 실체다.

그리고 이 구조가 주는 진짜 이득 — 코드는 값이 어디서 오는지 모른다. 코드는 그냥 DATABASE_URL이라는 이름표를 부를 뿐이고, 그 이름표에 무슨 값이 담기는지는 환경이 정한다. 내 노트북에서 돌면 .env의 값이, 클라우드에서 돌면 금고의 값이 그 이름표에 담긴다. 코드는 어느 쪽인지 알 필요가 없다. 그래서 코드를 한 줄도 고치지 않고 로컬과 클라우드를 오갈 수 있다. 이것이 환경변수라는 발상이 존재하는 근본 이유다.

[짚고 가기] 이 표에서 가장 헷갈리기 쉬운 지점이 ".env는 안 올라가는데 .env.example은 올라간다"는 대목이다. 차이는 딱 하나 — 값이 들어 있느냐 이다. .env는 진짜 값(시크릿)이 있어서 못 올리고, .env.example은 값이 빈 껍데기라 올려도 안전하다. "example은 안내판, env는 열쇠"라고 정리하면 기억에 남는다. 실습 3에서 저장소를 브라우저로 열어 실제로 .env는 없고 .env.example만 있는 것을 눈으로 확인하는 것이 이 개념의 최고의 마무리다.

콘솔과 대시보드

앞서 "콘솔에서 바꾸지 않는다"는 원칙이 여러 번 나왔으니, '콘솔'이 무엇인지도 잡아 두자. 콘솔(console) 또는 대시보드(dashboard) 는 클라우드 서비스가 제공하는 웹 관리 화면이다. GitHub·Cloudflare·Vercel에 로그인하면 나오는, 버튼과 설정 메뉴가 가득한 그 화면이 콘솔이다. 마우스로 클릭해서 서버를 켜고 설정을 바꿀 수 있다 — 편하다. 그러나 바로 그 편함이 눈송이 서버를 만드는 함정이다. 클릭은 기록·재현·검토를 남기지 않는다.

그래서 이 장의 태도는 명확하다 — 콘솔은 '보는 창'으로 쓰고, '바꾸는 손'으로는 쓰지 않는다. 배포된 서비스의 상태를 눈으로 확인하고, 로그를 들여다보고, 결과가 잘 나왔는지 보는 데는 콘솔이 훌륭하다. 하지만 설정을 바꾸는 일은 파일과 명령으로 한다. 이 구분이 몸에 배면, 여러분은 이미 인프라 담당의 핵심 습관을 갖춘 것이다.


15.3 인프라 담당의 역할 정의 — 네 칸

내용
판단 기준 설정 파일을 기준으로 삼는다. 재현 불가능한 변경은 하지 않은 것과 같다
금지 목록 콘솔에서 설정 변경 금지(보는 것은 허용) / 시크릿을 설정 파일·코드에 쓰기 금지 / 검토 없는 설정 적용 금지
프로세스 설정 파일 작성 → 사람 검토 → CLI로 적용 → 결과 확인 → CLAUDE.md에 기록
도구 권한 읽기부터 시작, 적용 명령은 건별 승인 (파괴적 명령은 훅이 차단)

이 네 칸은 앞선 장들에서 다른 역할(백엔드·프론트·리뷰어 등)을 정의하던 것과 같은 형식이다. AI에게 '인프라 담당'이라는 역할을 맡길 때, 이 네 칸이 그 역할의 성격을 규정한다. 하나씩 읽어 두면 실습 중 AI의 행동이 왜 그런지 이해된다.

IaC가 실무에서 하는 일을 몇 장면으로 감 잡아 두자.

이 네 장면을 실무의 언어로 조금 더 풀어 보자. 온티켓은 지금 작은 서비스라 와닿지 않을 수 있지만, 이 원칙이 왜 업계의 표준이 되었는지는 규모가 커진 상황을 상상해 보면 분명해진다.

온티켓은 아직 서버 한 대짜리 작은 서비스지만, 우리는 처음부터 이 원칙 위에서 짓는다. 작을 때부터 파일을 기준으로 삼으면, 커져도 그 방식이 그대로 확장된다. 반대로 작을 때 눈송이로 시작하면, 커진 뒤에 그것을 파일로 되돌리는 일이 훨씬 고통스럽다.

[짚고 가기] 이 네 장면은 "지금 우리 온티켓엔 과한 거 아닌가" 하는 속마음에 대한 답이다. 핵심은 — 원칙은 규모와 무관하게 같고, 작을 때 익혀 두면 커졌을 때 그대로 쓴다는 것이다. 실무 경험이 있다면 감사·온보딩 장면이 특히 와닿을 것이다. 회사에서 '이 설정 누가 바꿨어?'로 다퉈 본 적이 있다면, 바로 그 문제를 IaC가 푼다.


15.4 세팅 — 계정과 로그인 (사람의 일)

AI가 CLI를 실행하려면 먼저 각 서비스에 내 권한으로 로그인되어 있어야 한다. 로그인만큼은 사람의 일이다 — 권한을 넘기는 행위이기 때문이다.

이 절의 큰 그림을 먼저 잡자. 우리는 세 서비스(GitHub·Cloudflare·Vercel)를 쓰는데, 로그인의 성격이 조금씩 다르다. gh는 지금 바로 로그인해 둔다(오늘 저장소를 만들 것이므로). Cloudflare와 Vercel은 계정만 만들어 두고, 실제 로그인은 나중에 AI가 그 CLI를 실행하는 시점에 브라우저가 열리며 이뤄진다. 왜 이렇게 나뉘는지는 각 항목에서 설명한다.

로그인이 왜 '사람의 일'인지 다시 짚어 두자. 로그인은 "이 계정은 내 것이고, 내가 이 도구에 내 권한을 빌려준다"는 선언이다. 이건 대리인(AI)이 할 수 없는, 본인만 할 수 있는 일이다. 은행에서 대리인이 아무리 서류를 잘 준비해도 최종 본인 인증은 본인이 해야 하듯, CLI가 아무리 명령을 잘 만들어도 "이 계정이 내 것"이라는 증명은 사람이 브라우저에서 한다. 그래서 이 절의 모든 단계는 '사람의 일'로 표시돼 있다.

GitHub 계정과 gh

  1. https://github.com 가입 (이미 있다면 통과)
  2. gh 설치: https://cli.github.com 에서 설치 파일 다운로드·실행 (Windows·macOS 공통. 설치 후 터미널을 새로 연다)
  3. 터미널에서 로그인:
터미널
$ gh auth login

물음에는 GitHub.com → HTTPS → 브라우저 로그인 순으로 답하면 된다. 브라우저가 열리며 코드 입력·승인을 거치면 끝. gh auth status 로 확인.

각 물음이 무엇을 묻는지 알아 두면 당황하지 않는다. gh auth login을 실행하면 몇 가지를 순서대로 묻는다.

이 여덟 자리 코드 방식이 낯설 수 있는데, 원리는 이렇다 — 터미널(코드를 아는 쪽)과 브라우저(로그인한 계정을 아는 쪽)를 그 코드로 짝지어, "이 터미널이 이 계정의 것이 맞다"를 확인하는 것이다. 첫날 Claude Code에 로그인하던 방식과 형제 같은 흐름이다.

gh auth status는 "지금 어느 계정으로 로그인돼 있나"를 보여 주는 확인 명령이다. 여기에 내 GitHub 아이디가 보이면 gh가 내 권한을 정상적으로 쥔 것이다. 이제부터 AI가 gh 명령을 실행하면, 그것은 내 계정의 권한으로 실행된다.

[짚고 가기] gh 설치 방식은 OS·환경마다 조금씩 다르다(macOS는 Homebrew나 설치 파일, Windows는 설치 파일이나 winget 등). https://cli.github.com 의 안내를 따르되, 설치 후 터미널을 새로 여는 것을 잊지 말자 — Claude Code를 설치할 때 배운 "새 명령을 인식시키려면 터미널을 다시 연다"는 원리가 여기서 또 나온다. gh: command not found가 뜬다면 십중팔구 터미널을 안 닫았거나 설치가 덜 된 것이다.

Cloudflare와 Vercel

계정만 만들어 둔다 (둘 다 GitHub 계정으로 가입 가능 — 이 방식을 추천한다).

GitHub 계정으로 가입을 권하는 이유가 있다. 이 세 서비스는 서로 긴밀히 얽혀 일한다 — GitHub에 있는 코드를 Cloudflare와 Vercel이 바라보며 배포한다. 가입을 GitHub 계정으로 해 두면 이 연결이 처음부터 매끄럽고, 관리할 비밀번호도 하나 줄어든다. 'GitHub로 로그인' 버튼을 누르면 GitHub가 "이 서비스에 당신 계정 정보를 공유할까요?"를 묻고, 승인하면 가입이 끝난다. 별도의 아이디·비밀번호를 새로 만들지 않아도 된다.

두 서비스를 한 줄씩 소개해 두자. 오늘은 계정만 만들지만, 무엇을 하는 곳인지는 알아야 한다.

wrangler와 vercel CLI는 별도 설치 없이 프로젝트에서 바로 실행할 수 있다 (pnpm이 임시로 내려받아 실행해 준다). 로그인이 필요해지는 시점에 AI가 wrangler login 등을 실행하면 브라우저가 열리고 — 승인 버튼만 사람이 누른다.

여기서 "별도 설치 없이 바로 실행"이 무슨 뜻인지 풀어 두자. gh는 앞에서 직접 설치했는데, wrangler와 vercel은 왜 설치를 안 하는가? 우리 프로젝트는 이미 pnpm이라는 도구로 부품(패키지)을 관리하고 있는데, pnpm에는 "필요한 순간에 도구를 임시로 내려받아 실행하는" 기능이 있다. 그래서 wrangler나 vercel을 미리 깔아 둘 필요 없이, AI가 명령을 실행하는 순간 pnpm이 알아서 그 도구를 준비해 돌려 준다. 설치라는 단계 하나가 통째로 사라지는 셈이다.

그리고 로그인 시점이 gh와 다르다는 점을 짚어 두자. gh는 지금 미리 로그인해 두지만, wrangler·vercel은 AI가 그 CLI를 처음 실행하는 순간 로그인이 이뤄진다. AI가 wrangler login이나 vercel login을 실행하면 브라우저가 열리고, 사람은 열린 브라우저에서 '승인' 버튼만 누른다. 로그인 절차 자체는 AI가 시작하지만, 최종 승인 버튼은 사람의 손가락이 누른다 — 권한을 넘기는 그 마지막 한 번은 반드시 사람이라는 원칙이 여기서도 지켜진다.

[짚고 가기] 이 절에서 "로그인을 지금 안 해도 되나요?" 하고 조바심이 날 수 있다. Cloudflare·Vercel은 계정만 만들어 두면 되고, 실제 CLI 로그인은 실습 중 AI가 명령을 실행할 때 브라우저가 열리며 이뤄지니 걱정하지 않아도 된다. GitHub 계정으로 가입하면 실습이 훨씬 매끄럽다 — 이메일 인증 메일을 기다리는 시간이 사라진다. 네트워크가 느릴 때 특히 도움이 된다.


15.5 프롬프트 작성법 — 인프라를 시키는 요령

인프라를 프롬프트로 다룰 때의 공통 감각을 먼저 잡자. 다른 역할의 프롬프트와 결이 다른 점이 하나 있다 — "작성과 적용을 분리하고, 되돌리기 어려운 일 앞에서는 조사를 먼저 시킨다" 는 것이다. 코드를 짤 때는 일단 만들어 보고 고치면 되지만, 인프라는 세상에 공개하거나 클라우드에 반영하는 순간 되돌리기 어렵다. 그래서 인프라 프롬프트는 항상 '멈춤'을 하나씩 끼워 넣는다 — "조사부터 해", "설정만 만들고 배포는 하지 마", "연결까지만 하고 배포는 하지 마" 처럼. 이 멈춤이 인프라 담당의 신중함을 프롬프트로 구현한 것이다.

올리기 전에 — 전수조사부터

저장소에 올리는 것은 되돌리기 어려운 행동이다(이력은 지워지지 않는다). 그래서 push 전에 반드시 조사를 시킨다.

프롬프트
GitHub에 올리기 전 점검을 해줘:
1) 프로젝트 전체에서 시크릿(키·연결 문자열·비밀번호)이 코드나 설정 파일에
   박혀 있는 곳이 있는지 전수조사
2) .gitignore 가 .env 류, node_modules, 빌드 산출물을 다 제외하는지 확인
3) .env.example 이 실제 필요한 환경변수 목록과 일치하는지 대조
문제가 있으면 고치기 전에 목록으로 보고해.

이 프롬프트가 왜 좋은 프롬프트인지 뜯어 보자. 세 가지 점검을 구체적으로 열거했고 (막연히 "검사해줘"가 아니다), "문제가 있으면 고치기 전에 목록으로 보고해"로 자동 수정을 막고 사람의 판단을 끼워 넣었다. 인프라에서는 AI가 알아서 고치는 것보다, 무엇이 문제인지 먼저 사람에게 보고하게 하는 것이 안전하다 — 시크릿을 어떻게 처리할지는 판단이 필요한 일이기 때문이다.

'전수조사(全數調査)'라는 말도 짚어 두자. '전수'는 '전체 수(數)', 즉 하나도 빠뜨리지 않고 모두를 조사한다는 뜻이다. 표본만 보는 '샘플 조사'의 반대말이다. 시크릿 유출은 단 하나만 새어도 사고이므로, 표본이 아니라 전수여야 한다. AI는 프로젝트의 모든 파일을 빠르게 훑을 수 있어서 이런 전수조사에 특히 강하다 — 사람이 눈으로 수백 개 파일을 다 뒤지는 것보다 훨씬 빠르고 빠짐없다.

전수조사에서 AI가 실제로 무엇을 찾는지 감을 주자. 이런 것들이 코드에 실수로 박혀 있으면 안 된다.

찾는 것 생김새 예시 왜 위험한가
API 키 sk_live_..., AIza... 같은 긴 문자열 남이 우리 계정으로 결제·호출 가능
DB 연결 문자열 postgres://user:비번@host/db 데이터베이스 전체 노출
비밀번호 코드에 password = "..." 계정 탈취
토큰 ghp_... 같은 접근 토큰 저장소·서비스 권한 탈취

프롬프트를 상황에 맞게 변형하는 예도 몇 개 준비해 두자.

상황 이렇게 지시한다
점검 결과 시크릿이 발견됨 "발견된 시크릿을 .env로 옮기고, 코드에서는 환경변수로 불러오게 바꿔줘. .env.example에는 값 없이 이름만 추가해줘"
.gitignore가 부실함 ".gitignore에 빠진 항목(.env 류, node_modules, 빌드 산출물, .DS_Store 등)을 표준적으로 채워줘"
이미 올린 뒤 시크릿을 발견 "방금 push에 시크릿이 섞였어. 우선 그 시크릿을 즉시 폐기·재발급해야 하는지부터 알려주고, 이력에서 제거하는 방법을 안내해줘"

마지막 상황(이미 올린 뒤 발견)은 특히 중요한 감각을 담고 있다 — 한 번 올라간 시크릿은 '지운다'로 끝나지 않는다. 이력에 남아 있을 수 있으므로, 가장 확실한 대응은 그 시크릿 자체를 폐기하고 새로 발급받는 것이다. 도둑이 열쇠를 봤으면 자물쇠를 바꾸는 게 답이지, "열쇠를 숨겼다"가 답이 아닌 것과 같다. 그래서 애초에 올리기 전 전수조사가 이렇게 강조된다.

[짚고 가기] 여기서 "우리는 보안 훅도 세웠는데 왜 또 조사해요?"라는 의문이 든다. 답은 이렇다 — 훅은 '자동 방어벽'이고 전수조사는 '사람의 최종 눈'이다. 겹겹의 방어가 왜 필요한지 보여 주는 대목이다. 훅이 막지 못하는 형태의 시크릿(예: 새로운 패턴)도 있을 수 있으니, 되돌리기 어려운 행동 앞에서는 자동 방어에만 의존하지 않고 한 번 더 조사한다 — 이 태도 자체가 인프라 담당의 성숙함이다.

저장소 생성과 push — 전부 프롬프트로

프롬프트
gh 로 GitHub에 비공개 저장소 onticket 을 만들고, 지금까지의 작업을
첫 커밋으로 올려줘. 커밋 메시지는 한국어로 의미 있게.
끝나면 저장소 주소를 알려줘.

AI가 git 초기화·커밋·저장소 생성·push를 이어서 실행한다. 사람은 각 명령을 승인하며 무엇을 하는 명령인지 한 줄씩 읽는다.

이 짧은 프롬프트 하나가 실제로는 여러 단계의 명령으로 풀린다. 승인 창에서 지나갈 명령들을 미리 알아 두면, 각 승인이 무슨 뜻인지 읽을 수 있다.

단계 AI가 실행하는 것
초기화 git init 이 폴더를 저장소로 만든다(이력 관리 시작)
담기 git add 올릴 파일들을 커밋 대상에 담는다
커밋 git commit 현재 상태를 이력의 한 지점으로 새긴다
저장소 생성 gh repo create onticket --private GitHub에 비공개 저장소를 만든다
올리기 git push 커밋을 GitHub로 밀어 올린다

프롬프트에서 신경 쓴 세 가지를 짚어 두자.

프롬프트 변형 예도 준비해 두자.

원하는 것 이렇게 지시한다
저장소 이름을 다르게 "저장소 이름을 onticket-service로 만들어줘"
설명을 붙이고 싶다 "저장소에 '온티켓 티켓 예매 서비스'라는 설명(description)도 달아줘"
올리기 전 한 번 더 확인 "push 직전에 올라갈 파일 목록을 먼저 보여줘. .env가 목록에 없는 걸 내가 확인한 뒤 올릴게"

마지막 변형("올라갈 파일 목록을 먼저 보여줘")은 신중함을 한 단계 더한 좋은 습관이다. 실제로 밀어 올리기 직전에 "무엇이 올라가는지"를 눈으로 확인하면, .env가 섞여 들어가는 사고를 마지막 순간에 잡을 수 있다.

[짚고 가기] 이 실습에서는 승인 창이 여러 번 연속으로 뜬다. 지쳐서 엔터를 연타하기 쉬운 지점이다. 여기서 첫 실습부터 다져 온 "읽고 누르기"를 다시 떠올리자. 특히 git push 승인은 "이것이 코드를 세상에 올리는 그 순간"이라는 점을 기억하면, 잠깐 멈춰 파일 목록을 확인하는 습관이 든다. 위에서 명령들을 표로 미리 정리해 둔 것도 이 때문이다 — 어떤 명령이 지나가는지 알면 덜 불안하다.

배포 설정 작성 — 적용과 분리해서

프롬프트
api/ 에 wrangler.toml 을 작성해줘. 앱 이름은 onticket-api.
아직 배포는 하지 마 — 설정 파일만 만들고, 각 항목이 무슨 뜻인지
주석으로 설명을 달아줘.

"아직 배포는 하지 마"— 설정 작성과 적용을 분리하는 것이 인프라 프로세스의 기본기다. 파일을 먼저 만들고, 사람이 읽고, 적용은 그다음이다.

이 프롬프트에 담긴 세 가지 요령을 뜯어 보자.

'주석(comment)'이라는 용어를 짚어 두자. 주석은 파일 안에 적지만 컴퓨터는 무시하고 사람만 읽는 설명글이다. 도구는 주석을 건너뛰고 실제 설정만 읽는다. 그래서 주석을 아무리 많이 달아도 배포 동작에는 영향이 없고, 오직 읽는 사람에게 도움만 준다. TOML 파일에서는 #으로 시작하는 줄이 주석이다.

이 '작성과 적용의 분리'는 인프라 전반에 통하는 패턴이라, 다른 설정에도 그대로 쓴다. 변형 예를 보자.

상황 이렇게 지시한다
설정을 읽고 검토만 "생성된 wrangler.toml을 한 줄씩 읽고, 각 항목이 왜 필요한지 설명해줘. 아직 아무것도 실행하지 마"
배포 명령을 미리 알고 싶다 "이 설정으로 배포한다면 어떤 명령을 실행하게 되는지, 그 명령이 무슨 일을 하는지만 알려줘. 실행은 하지 마"
설정이 이해 안 됨 "compatibility_date 이 줄은 왜 필요해? 없으면 어떻게 돼?"

세 번째 변형처럼 "이 줄은 왜 필요해?" 를 그 자리에서 묻는 습관이 이 장에서 특히 값지다. 설정 파일은 한 줄 한 줄이 이유를 갖는다. 이유를 모르는 줄을 그냥 두면, 나중에 그 줄이 문제를 일으켰을 때 손댈 수 없다. 파일을 읽다 막히면 즉시 AI에게 물어, 모든 줄의 이유를 아는 상태로 승인하는 것이 인프라 담당의 태도다.

[짚고 가기] "설정 작성과 적용의 분리"는 이 절의 핵심 교훈이다. 왜 나누는지 비유로 이해하면 쉽다 — 건축에서 설계도를 그리는 일(작성)과 실제로 벽을 세우는 일(적용)을 나누고, 그 사이에 도면 검토가 들어가는 것과 같다. 벽을 세운 뒤에는 고치기 어렵지만, 도면은 얼마든지 검토하고 고칠 수 있다. 인프라도 똑같다.


15.6 실습 — 코드가 세상의 보관소로

이제 실제로 우리 코드를 세상의 보관소로 올리고, 배포의 길을 닦는다. 이 실습의 큰 리듬은 첫 페이지를 만들 때 배운 것과 같다 — 지시하고, 승인하고, 확인한다. 다만 이번엔 승인의 무게가 다르다. 각 단계를 서두르지 말고, 특히 확인 단계를 꼼꼼히 하자.

따라하기 1 — gh 로그인

위 '세팅 — 계정과 로그인'의 절차로 gh를 설치하고 gh auth login을 완료한다. gh auth status에서 내 계정이 보이면 준비 끝.

이 단계는 사람의 일이다 — 권한을 여는 일이므로 AI가 대신할 수 없다. gh auth status에 내 GitHub 아이디가 보이는 것을 눈으로 확인하고 넘어가자. 여기가 안 되면 뒤의 모든 단계가 안 되므로, 이 확인을 반드시 하고 진행한다.

따라하기 2 — push 전 전수조사

아래 프롬프트로 push 전 전수조사를 실행한다.

프롬프트
GitHub에 올리기 전 점검을 해줘:
1) 프로젝트 전체에서 시크릿(키·연결 문자열·비밀번호)이 코드나 설정 파일에
   박혀 있는 곳이 있는지 전수조사
2) .gitignore 가 .env 류, node_modules, 빌드 산출물을 다 제외하는지 확인
3) .env.example 이 실제 필요한 환경변수 목록과 일치하는지 대조
문제가 있으면 고치기 전에 목록으로 보고해.

위 프롬프트를 그대로 복사해 입력하면 된다. 다른 내용으로 바꿔서 해 보고 싶다면 자유롭게 바꿔도 좋다.

보고를 읽고 문제가 있으면 처리를 지시한다. (보안 훅이 잘 서 있다면 이 단계는 대부분 "이상 없음"으로 지나간다 — 문이 있으니 조사가 짧아진다. 겹겹의 방어가 주는 여유다.)

보고가 "이상 없음"으로 나와도 그냥 넘기지 말고, AI가 무엇을 조사했는지 한 번 읽자. "코드 전체에서 시크릿 패턴을 훑었고, .gitignore.env를 제외하며, .env.example이 목록과 일치한다"는 식의 보고여야 한다. 만약 시크릿이 발견되면, AI가 자동으로 고치기 전에 목록으로 보고하도록 프롬프트를 짰으므로, 그 목록을 보고 처리 방향(대개 .env로 옮기고 코드는 환경변수로 부르게)을 지시한다.

따라하기 3 — 저장소 생성과 첫 push

아래 프롬프트로 저장소 생성과 첫 push를 실행한다.

프롬프트
gh 로 GitHub에 비공개 저장소 onticket 을 만들고, 지금까지의 작업을
첫 커밋으로 올려줘. 커밋 메시지는 한국어로 의미 있게.
끝나면 저장소 주소를 알려줘.

위 프롬프트를 그대로 복사해 입력하면 된다. 다른 내용으로 바꿔서 해 보고 싶다면 자유롭게 바꿔도 좋다.

승인을 거치며 명령들이 지나가고, 저장소 주소가 돌아온다. 브라우저로 그 주소를 열어 눈으로 확인한다.

이 세 가지 확인이 이 장 전체에서 가장 중요한 순간이다. 하나씩 왜 확인하는지 짚자.

'팀 정의도 코드'라는 이 발상을 한 번 더 음미하자. 보통 "코드를 올린다"고 하면 프로그램만 떠올린다. 그러나 우리 저장소에는 프로그램과 나란히, 그 프로그램을 어떻게 다루고 발전시킬지에 대한 규칙이 함께 담긴다. 사람이 바뀌어도, AI 도구가 바뀌어도, 이 규칙 파일들이 기준으로 남아 프로젝트의 일관성을 지킨다. IaC가 인프라를 파일로 붙잡았듯, 우리는 팀의 일하는 방식까지 파일로 붙잡은 셈이다.

[짚고 가기] 이 세 확인은 반드시 다 함께 하자. 특히 두 번째(.env 없음)는 직접 자기 저장소를 열어 눈으로 확인해야 한다 — 말로 "없을 거예요"가 아니라 파일 목록을 손가락으로 짚으며 "없다"를 확인하는 경험이 개념을 각인시킨다. 세 번째(팀 정의)는 이 과정 전체를 되돌아보는 좋은 순간이다. 3일간 만든 게 코드만이 아니라 팀 자체였고, 그 팀의 구성이 이제 파일로 저장소에 남는다 — 이 정리가 큰 성취감을 준다.

따라하기 4 — wrangler.toml 작성과 검토

아래 프롬프트로 배포 설정을 작성하고, 생성된 파일을 연다.

프롬프트
api/ 에 wrangler.toml 을 작성해줘. 앱 이름은 onticket-api.
아직 배포는 하지 마 — 설정 파일만 만들고, 각 항목이 무슨 뜻인지
주석으로 설명을 달아줘.

위 프롬프트를 그대로 복사해 입력하면 된다. 다른 내용으로 바꿔서 해 보고 싶다면 자유롭게 바꿔도 좋다.

주석을 따라 한 줄씩 읽는다 — 이름, 진입점, 호환성 설정. 이해 안 되는 항목은 그 자리에서 묻는다. ("이 줄은 왜 필요해?")

파일을 열면 예상보다 짧다는 데 안심하게 된다 — 대개 열 줄 안팎이다. AI가 달아 준 주석을 따라 한 줄씩 소리 내어 읽어 보자. "이건 앱 이름(name), 이건 진입점(main), 이건 호환성 날짜(compatibility_date)…" 용어 정리에서 미리 본 항목들이 실제 파일에 있는 것을 확인하는 순간이다. 주석이 있어도 이해 안 되는 줄이 있으면, 그 자리에서 AI에게 묻는다. "이 줄은 왜 필요해? 없으면 어떻게 돼?" 모든 줄의 이유를 아는 상태가 되면, 이 파일이 곧 우리 API 서버라는 인프라의 '기준 자료'라는 감각이 붙는다.

여기서 중요한 것 하나 — 이 단계에서 우리는 파일을 만들고 읽기만 하지, 배포하지 않는다. 프롬프트에 "아직 배포는 하지 마"를 넣은 이유가 이것이다. 설계도를 그리고 검토하는 단계이고, 실제로 벽을 세우는(배포하는) 일은 다음 단계의 몫이다. 지금은 파일에 기록한 기준을 갖춰 두는 것으로 충분하다.

따라하기 5 — Vercel 연결 준비

프롬프트
web/ 을 Vercel에 배포할 준비를 해줘. vercel CLI로 로그인부터 —
브라우저 승인은 내가 한다. 프로젝트 연결(link)까지만 하고 배포는 하지 마.

위 프롬프트를 그대로 복사해 입력하면 된다. 다른 내용으로 바꿔서 해 보고 싶다면 자유롭게 바꿔도 좋다.

브라우저 승인 후, 연결 상태를 확인한다. (배포 버튼은 아직 누르지 않는다 — 지금은 길을 닦아 두는 것이다.)

이 프롬프트도 인프라의 두 원칙을 그대로 담고 있다 — "로그인은 사람이"(브라우저 승인은 내가 한다)와 "작성/연결과 적용의 분리"(연결까지만, 배포는 하지 마). AI가 vercel login을 실행하면 브라우저가 열린다. 여기서 사람이 '승인' 버튼을 누른다 — 권한을 넘기는 그 한 번이다. 그다음 AI가 vercel link로 우리 web/ 폴더를 Vercel의 한 프로젝트에 연결한다.

'연결(link)'이 무엇인지 짚어 두자. link는 "이 폴더가 Vercel의 이 프로젝트다"라고 짝을 지어 두는 일이다. 아직 코드를 배포하는 것이 아니라, "나중에 배포하면 이 프로젝트로 간다"는 길만 놓는 것이다. 그래서 이 단계 뒤에도 실제 서비스는 아직 세상에 뜨지 않는다. 배포라는 마지막 버튼은 다음 단계(실제 배포)의 몫으로 남겨 둔다 — 지금은 그 버튼까지 이어지는 길을 닦아 두는 것이다.

연결이 끝나면 web/ 폴더에 Vercel이 만든 작은 설정 폴더(.vercel)가 생긴다. 이 폴더는 "이 프로젝트가 Vercel의 어느 프로젝트와 연결됐는지"를 담는데, 그 안에는 노출되면 안 되는 식별자도 있어서 보통 .gitignore로 저장소에서 제외한다. AI가 연결을 마친 뒤 이 처리까지 했는지 한 번 확인하면 좋다.

[짚고 가기] 이 단계에서 "왜 배포까지 안 해요? 다 왔는데" 하고 아쉬울 수 있다. 하지만 오늘의 역할은 '인프라 준비'이지 '배포 실행'이 아니다. 길을 닦는 것과 차를 달리게 하는 것은 다른 일이다. 실제 배포는 준비가 다 된 상태에서 마지막에 한 번에 하는 것이 안전하다. 이 '멈춤의 절제'가 인프라 담당의 성숙함이라는 것을 알고 나면, 아쉬움이 이해로 바뀐다.

따라하기 6 — 기록

프롬프트
CLAUDE.md에 인프라 정보를 추가해줘:
- 저장소: (주소)
- api 배포: Cloudflare Workers, 설정은 api/wrangler.toml
- web 배포: Vercel (연결됨, 미배포)
- 원칙: 설정 파일이 기준, 콘솔 변경 금지, 시크릿은 각 배포처 금고에

위 프롬프트를 그대로 복사해 입력하면 된다. 다른 내용으로 바꿔서 해 보고 싶다면 자유롭게 바꿔도 좋다.

이 마지막 단계가 인프라 프로세스의 다섯 번째 칸('기록')을 실천하는 것이다. 우리가 오늘 구축한 인프라의 지도 — 저장소가 어디 있고, 무엇이 어디에 배포되며, 어떤 원칙을 따르는지 — 를 CLAUDE.md에 남긴다. 왜 굳이 기록하는가? 다음에 이 프로젝트를 여는 사람(또는 AI)이 이 파일만 읽으면 "우리 인프라가 어떻게 생겼는지"를 즉시 알 수 있기 때문이다. 이 장 첫머리의 '문서가 기준', 역할 정의에서 본 '온보딩' 장면이 여기서 완성된다 — 인프라 구조 자체를 문서로 붙잡아 두는 것이다.

특히 마지막 줄(원칙)을 기록하는 것이 값지다. 인프라 정보뿐 아니라 인프라를 다루는 원칙까지 CLAUDE.md에 적어 두면, 다음에 이 프로젝트에서 일할 AI가 그 원칙을 읽고 따른다. "콘솔에서 바꾸지 마라, 시크릿은 금고에 둬라"가 파일에 적혀 있으면, 사람이 매번 상기시키지 않아도 규칙이 지켜진다. 규칙도 기준 자료(파일)로 붙잡아 두는 것이다.

완료 기준 체크리스트

이 체크리스트의 마지막 항목은 손이 아니라 머리로 통과하는 항목이라는 점을 눈여겨보자. 저장소도 만들고 파일도 갖췄지만, 이 장의 진짜 성취는 "왜 파일이 기준인가"를 자기 말로 설명할 수 있게 되는 것이다. 옆 사람에게 "재현·기록·검토, 이 셋 때문이야"라고 말할 수 있으면, 여러분은 인프라 담당의 제1원칙을 몸에 새긴 것이다.

[짚고 가기] 체크리스트는 옆 사람과 짝지어 서로 점검해 보면 좋다. 특히 마지막 두 항목 — "wrangler.toml 각 항목을 설명해 봐", "설정 파일이 기준인 이유 셋을 말해 봐" — 을 서로 묻고 답해 보면, 손으로 한 실습이 머릿속 개념으로 정리된다. 대답이 막힌다면 이 장의 '용어 정리'와 '개념' 절로 잠깐 돌아가면 된다.


15.7 정리

오명운 · macro@prag-ai.com