t-box를 부숴보고, 제대로 다시 만든다
보안을 고려하지 않고 만든 사내 파일 공유 앱 t-box를 직접 공격해 “왜 위험한지”를 몸으로 느끼고 → AI와 함께 제대로 된 서비스를 설계한 뒤 → 그걸 완성해 오는 흐름. 코드 암기가 목적이 아니라, AI와 요구사항을 정리하고 결과를 검증하는 일하는 방식을 익히는 시간임.
HOW 이 화면 사용법
- 충님의 설명 들으며 위에서 아래로 순서대로 따라감.
- 각 단계 “지금 할 일” 체크하면 진행률 올라감.
- 프롬프트 카드는 복사 버튼으로 그대로 AI에 붙여넣음.
- 왼쪽 목차로 언제든 이동 · 현재 위치 표시됨.
GOAL 오늘 잡을 감각
- 보안을 고려하지 않은 서비스가 얼마나 쉽게 뚫리는지 직접 겪는다.
- 화면에서 숨기는 건 보안이 아니다 — 서버가 막아야 한다.
- 보안은 나중이 아니라 설계할 때부터 넣는다.
- AI에게 만들게 하고, 의심하게 하고, 검증한다.
실습 안전 수칙. 오늘의 모든 공격 실습은 본인 VM의 교육용 t-box 앱 안에서만 진행함. 외부 사이트, 회사 실제 시스템, 다른 참가자 VM 대상 금지. 허가되지 않은 스캔·자동화 공격 금지.
그리고 토큰·API 키·비밀번호는 AI 대화창에 절대 입력하지 마.
오프닝 · 오늘의 목표
오늘은 순서가 거꾸로임. 먼저 보안을 고려하지 않은 서비스를 직접 부숴보고, 그다음 “제대로 만들려면?”을 AI와 설계함.
충님의 설명 ›
오늘은 개발 문법을 외우는 시간이 아닙니다. 우리가 다룰 건 t-box라는 작은 파일 공유 서비스인데, 오늘은 먼저 보안을 고려하지 않고 만든 버전을 직접 공격해볼 겁니다. 클릭 몇 번으로 남의 파일이 지워지고, 숨긴 자료가 보이는 걸 눈으로 확인할 거예요.
그렇게 “왜 위험한지”를 몸으로 느낀 다음, AI와 함께 제대로 된 서비스를 설계합니다. 그걸 직접 완성해 오는 게 오늘의 숙제예요.
AI가 코드를 대신 써줄 수는 있지만, 무엇이 안전하고 쓸 만한 서비스인지는 사람이 판단해야 합니다.
- 부순다 — 보안을 고려하지 않은 t-box를 내려받아 실행하고, 직접 공격해본다
- 이해한다 — 왜 이렇게 쉽게 뚫렸는지, 제대로면 뭐가 달라야 하는지
- 설계한다 — 보안을 처음부터 넣은 PRD·아키텍처를 AI와 만든다
- 만들어 온다 — 제대로 된 t-box를 완성하는 게 숙제
브라우저에서 앱까지 · 전체 구조
도메인을 입력하면 요청이 어떤 길을 거쳐 우리 앱에 도달하는지 파악함.
-
브라우저사용자가 주소를 입력하고 화면을 보는 곳
-
도메인 · DNS도메인을 실제 서버 IP로 바꿔줌 · 우리 서버 아니고 인터넷에 있는 주소록
-
웹 서버 · t-box 앱요청을 받아 처리하는 우리 프로그램 · HTTPS로 암호화되어 오갑니다
-
데이터베이스파일 정보 · 사용자 · 감사 로그를 저장 · 만들고·읽고·고치고·지움(CRUD)
-
파일 저장소실제 업로드된 파일을 보관
충님의 설명 ›
주소창에 도메인을 입력해도, 요청이 곧바로 우리 앱에 닿는 건 아닙니다. 먼저 DNS가 도메인(예: study.tla.so)을 실제 서버 주소(IP)로 바꿔줘요.
이 DNS는 우리 서버 안에 있지 않습니다. 인터넷 곳곳에 흩어진 “주소록 서버”예요. 도메인을 등록한 곳(Cloudflare, AWS Route 53, 가비아 등)이 “이 도메인 = 이 IP”라는 기록을 관리하고, 브라우저는 보통 통신사(ISP)나 공용 DNS(예: 8.8.8.8)에 물어서 그 IP를 받아옵니다.
IP를 알아낸 뒤에야 그 서버의 t-box 앱이 요청을 처리합니다. 이때 앱은 데이터를 만들고(Create)·읽고(Read)·고치고(Update)·지우는데(Delete), 이 네 가지를 묶어 CRUD라고 불러요. 파일 정보·기록은 데이터베이스에, 실제 파일은 파일 저장소에 두고 CRUD 합니다. 통신은 HTTPS로 암호화되고요.
핵심 순서 — 도메인을 IP로 찾고(DNS·외부 서비스) → 그 서버의 앱이 요청을 처리하고 → 데이터를 만들고·읽고·고치고·지웁니다(CRUD · DB·파일 저장소).
터미널에 Claude Code 설치
오늘 프롬프트는 전부 Claude Code에 붙여넣음. 터미널 창 2개 필요함 — 하나는 Claude Code용, 하나는 명령어 입력용.
충님의 설명 ›
Claude Code는 터미널(명령어 창)에서 바이브 코딩을 할 수 있는 AI 코딩 에이전트 도구예요. 오늘의 프롬프트는 전부 여기에 붙여넣습니다. 설치는 명령어 한 줄이면 끝나고, 처음 실행하면 뜨는 로그인 안내는 충님이 알려드립니다.
작업 폴더는 /var/www/html을 씁니다. 그런데 지금 VM엔 웹서버가 없어서 이 폴더가 아직 없어요. 그래서 sudo로 폴더를 만들고 내 계정 소유로 바꾼 다음 그 안에서 작업합니다.
그런데 문제가 하나 있어요. Claude Code가 설치 명령을 대신 실행할 때 sudo가 비밀번호를 물으면, AI는 비밀번호를 입력할 수 없어서 거기서 멈춰버립니다. 그래서 시작 전에 “이 실습 계정은 비밀번호 없이 sudo를 쓸 수 있게” 한 번 설정해 둘 거예요.
이 설정도 직접 외울 필요 없어요. Claude Code에게 명령어를 물어보고, 받은 걸 터미널에 붙여넣는 방식으로 해봅니다.
그래서 오늘은 터미널 창을 2개 띄워두고 씁니다. 하나는 Claude Code 전용, 다른 하나는 명령어 입력용이에요. 한 창에서 번갈아 하면 Claude Code를 껐다 켰다 해야 해서 번거롭거든요.
SSH로 접속했다면 창을 하나 더 열어 같은 VM에 한 번 더 접속하면 됨. 아래 ①②는 터미널 B, ③은 터미널 A에서 실행함.
curl -fsSL https://claude.ai/install.sh | bashsudo mkdir -p /var/www/html
sudo chown -R $USER /var/www/htmlcd /var/www/html
claudeclaude 처음 실행하면 로그인 안내가 나옴. 로그인한 뒤(또는 /login) 프롬프트 창에 한글로 요청 입력하면 됨. 터미널 B도 cd /var/www/html 해두면 편함.
- sudo
- “관리자 권한으로 실행”이란 뜻임. 시스템 폴더 만들거나 프로그램 설치할 땐 권한이 필요해서 명령 앞에 붙임. 비번 물으면 충님이 알려준 거 입력해 — 아래 ④에서 안 묻게 설정함.
- sudo chown -R $USER /var/www/html
/var/www/html폴더와 그 안의 모든 것(-R)의 소유자를 지금 나($USER)로 바꿉니다. 이래야 앞으로sudo없이도 그 폴더에서 자유롭게 파일을 만들고 지울 수 있어요.
첫 바이브 코딩 연습임. 터미널 A(Claude Code)에 아래 프롬프트 붙여넣어 명령어를 받고, 그걸 터미널 B에 붙여넣어 직접 실행함.
지금 이 리눅스 계정이 sudo를 쓸 때 비밀번호를 묻지 않도록 설정하고 싶어.
교육용 실습 VM이고, 내가 관리자 권한을 가지고 있어.
- visudo로 문법 검사를 하면서 /etc/sudoers.d/ 아래에 파일을 만드는 방식으로 알려줘
- 내 계정 이름은 직접 확인해서 넣어줘 (whoami)
- 실행할 명령어를 복사해서 쓸 수 있게 알려주고, 설정이 잘 됐는지 확인하는 방법도 알려줘
명령은 네가 실행하지 말고, 내가 터미널에 붙여넣어 직접 실행할게.
왜 “직접” 실행하냐? sudo 권한 설정은 시스템에서 가장 조심해야 할 작업 중 하나임. AI가 준 명령을 한 번 읽어보고 내 손으로 실행하는 습관이, 오늘 배울 “AI에게 맡기되 검증한다”의 첫 연습임.
받은 명령을 터미널 B에 붙여넣어 실행한 뒤 아래로 확인함. OK 나오면 성공.
sudo -n true && echo "OK" || echo "아직 비밀번호를 묻습니다"보안을 고려하지 않고 만든 t-box 실행
오늘은 먼저 부숴봄. 충님이 미리 만들어 둔 보안을 고려하지 않은 파일 공유 앱을 각자 VM에 올리고 내 도메인으로 접속되게 만듦. 이게 뒤 해킹 실습 대상임.
충님의 설명 ›
보통은 “만들고 → 고친다” 순서로 배우지만, 오늘은 반대로 갑니다. 먼저 보안을 고려하지 않은 서비스를 직접 공격해보고, “아, 이래서 위험하구나”를 몸으로 느낀 다음에 “그럼 제대로 만들려면?”을 이야기할 거예요.
이 앱은 순수 PHP + PostgreSQL로 만든 아주 작은 파일 공유 앱입니다. 로그인·권한·검증이 일부러 다 빠져 있어요. 저장소에 설치 안내서(INSTALL.md)가 들어 있어서, 코드를 내려받은 뒤 Claude Code에게 “INSTALL.md 읽고 설치해줘”라고만 하면 됩니다.
터미널 B에서 코드를 /var/www/html에 받음. (Claude Code 돌아가는 A는 그대로 둠.)
cd /var/www
sudo rm -rf html
sudo git clone https://git2.tla.so/hardline7/t-box-sample.git html
sudo chown -R $USER /var/www/html
cd /var/www/html코드를 새로 받았으니 터미널 A에서도 cd /var/www/html 다시 입력 필요함. 안 하면 Claude Code가 옛 폴더를 봄.
저장소 안에 INSTALL.md라는 설치 안내서가 들어 있음. 명령어를 하나씩 칠 필요 없이, 터미널 A에 아래 한 줄만 붙여넣으면 Claude Code가 웹서버·DB·nginx 설정까지 알아서 해줌.
/var/www/html 의 INSTALL.md 를 읽고,
t-box가 내 VM에서 잘 실행되도록 설치해줘.
내 도메인은 "내이메일앞자리.tla.so" 야.
설치가 끝나면 브라우저로 접속되는지 확인하는 방법도 알려줘.
중간에 sudo 비번을 안 물어야 안 멈춤 — 그건 앞 단계(sudo 설정)에서 이미 처리했음.
내 도메인으로 접속하면 파일 목록(5개)이랑 업로드 폼 뜨냐? 위쪽 역할 전환 박스에서 Admin/Employee/Guest 바뀌냐?
해킹 타임 1 · 프론트 권한 우회 & XSS
공격 기술 학습이 아님. 잘못 만든 서비스가 왜 위험한지 직접 체감하는 시간임.
내 VM의 교육용 t-box에서만. 외부·회사 실제 시스템·타 참가자 VM 금지.
설치할 때 schema.sql이 예시 파일 5개를 이미 넣어놨음. 따로 업로드할 필요 없이 바로 시작하면 됨.
| 파일명 | 접근 레벨 |
|---|---|
| 회사소개.txt · 제품안내.txt | public |
| 사내공지.txt · 회의록.txt | internal |
| 급여명세_2026.txt | admin-only ← 뒤에서 “안 보여야 하는데 보이는” 주인공 |
목록이 비어 있으면 설치가 덜 된 거임 → INSTALL.md의 DB 단계를 다시 실행.
Employee에겐 삭제 버튼이 화면에서 숨겨져 있을 뿐, 버튼 자체는 브라우저 안에 그대로 있음. 숨긴 걸 다시 보이게 만들어 눌러봄.
| ID | 파일명 | 접근 레벨 | 동작 |
|---|---|---|---|
| 1 | 회사소개.txt | public | 받기 삭제 |
| 3 | 사내공지.txt | internal | 받기 삭제 |
| 5 | 급여명세_2026.txt | admin-only | 받기 삭제 |
- 1Admin이라 삭제 버튼 보이고 admin-only 파일(급여명세)도 목록에 있음. 정상임.
| ID | 파일명 | 접근 레벨 | 동작 |
|---|---|---|---|
| 1 | 회사소개.txt | public | 받기 — 삭제 버튼만 숨김 |
| 3 | 사내공지.txt | internal | 받기 — 삭제 버튼만 숨김 |
| 5 | 급여명세_2026.txt | admin-only | 받기 — 삭제 버튼만 숨김 |
- 2Employee인데 삭제 버튼만 사라졌을 뿐, 급여명세(admin-only)까지 그대로 보이고 “받기”도 눌립니다. 화면만 손봤을 뿐 서버는 아무도 안 막고 있어요. 여기서부터 실습 시작.
- Employee 계정으로 전환 → 목록에 삭제 버튼이 안 보이는 것 확인
- F12를 눌러 개발자도구 열기 → Elements(요소) 탭 선택
- 왼쪽 위 화살표 아이콘(Ctrl+Shift+C)을 켜고 파일 목록의 한 줄을 클릭 → 그 줄의 HTML로 이동
- 그 근처에서 삭제 버튼 태그를 찾습니다.
style="display:none"이나hidden,class="hidden"이 붙어 있을 거임 - 그 부분을 더블클릭해서 지우고 Enter → 화면에 삭제 버튼이 나타납니다
- 나타난 삭제 버튼을 클릭 → 파일이 진짜로 삭제되는지 확인
<td class="actions">
<a class="btn btn-ghost" href="api/download.php?id=3">받기</a>
<button class="btn btn-danger js-delete" data-id="3"
style="display:none">삭제</button>
</td>
- 3버튼은 지워진 게 아니라 그대로 있음. 빨갛게 칠한
style="display:none"만 더블클릭해서 지우고 Enter 쳐.
| 3 | 사내공지.txt | internal | 받기 삭제 |
// 삭제 버튼을 누르면 콘솔에 찍히는 서버 응답
{
"ok": true,
"deleted": "사내공지.txt",
"by": "employee01 (Employee)",
"note": "서버가 권한을 확인하지 않았습니다"
}
- 4Employee가 눌렀는데 서버가 그대로 삭제함. 서버는 “누가 보냈는지” 확인조차 안 함.
방금 무슨 일이 일어난 거임? 서버를 해킹한 게 아니라 내 브라우저 화면을 고쳤을 뿐임. 그런데 서버는 그 요청을 그대로 받아서 파일을 지움. 화면은 사용자 편의일 뿐 보안 장치가 아니라는 증거임.
버튼을 못 찾겠으면 콘솔에서 API를 직접 불러도 결과는 같음. 파일 ID(id=3)는 목록에 보이는 번호로 바꿔야 함 — Network 탭에서 실제 삭제 요청 주소 확인 가능함.
fetch("api/files.php?id=3", { method: "DELETE" })
.then((res) => res.json())
.then(console.log);콘솔에 코드를 처음 붙여넣으면 브라우저가 경고 띄우고 막음. “모르는 코드를 붙여넣게 해서 계정을 뺏는 사기”를 막으려는 장치임. 아래 순서로 한 번만 풀어.
- F12 → Console(콘솔) 탭으로 이동
- 붙여넣기를 시도하면 “이해하지 못했거나 직접 검토하지 않은 코드는 붙여넣지 마세요…” 경고가 뜹니다
- 콘솔에 아래 문구를 직접 타이핑하고 Enter
한글 브라우저붙여넣기 허용영문 브라우저allow pasting복사·붙여넣기 말고 손으로 쳐야 합니다. 둘 중 어느 걸 쓸지는 화면에 뜬 경고문 마지막 줄에 적혀 있어요. - 이제 위 코드를 붙여넣고 Enter → 파일이 삭제되는지 확인
이 경고가 왜 있는지 기억해 둬. 실제로 “이 코드를 콘솔에 붙여넣으면 이벤트 당첨”처럼 속여서 계정을 탈취하는 공격(셀프 XSS)이 흔함. 오늘처럼 내가 만든 실습 앱 아니면, 남이 준 코드를 콘솔에 붙여넣지 마.
Guest로 바꿔봄. 그래도 관리자 전용 급여명세_2026.txt가 목록에 보이고 “받기”를 누르면 실제로 내려받아짐. 화면에서 숨기지도 않은, 가장 노골적인 정보 유출임.
원인은 서버임. 개발자도구 Network 탭에서 api/files.php 응답을 열면 서버가 역할과 상관없이 모든 파일을 통째로 내려주는 게 보임.
- 위쪽 역할 전환을 Guest로 바꾸고 → 급여명세 파일이 보이는지 확인
- 그 줄의 “받기”를 눌러 실제로 내려받아지는지 확인
- F12 → Network 탭 → 새로고침 →
files.php응답에 admin-only가 있는지 확인
api/files.php 응답 요청자: guest01{
"user": { "name": "guest01", "role": "Guest" },
"files": [
{ "id": 1, "original_name": "회사소개.txt", "access_level": "public" },
{ "id": 3, "original_name": "사내공지.txt", "access_level": "internal" },
{ "id": 5, "original_name": "급여명세_2026.txt", "access_level": "admin-only" }
]
}
- !Guest 요청인데 서버가 admin-only 파일까지 다 내려줌. 화면 필터가 있든 없든 권한 없는 데이터를 서버가 내려준 순간 이미 유출임.
api/download.php?id=5로 내용까지 받아짐.
파일명이나 설명에 아래 값을 넣고 목록 화면으로 가면, 값이 글자가 아니라 코드로 실행됨.
<script>alert('나는 해커다!! 이 서비스는 해킹됐다!!')</script><img src=x onerror="alert('나는 해커다!! 이 서비스는 해킹됐다!!')">- 1설명은 그냥 글자일 뿐인데 서버가 검사 없이 저장하고 화면이 그대로 HTML로 출력함.
이 서비스는 해킹됐다!!
- 2내가 올린 파일을 다른 사람이 목록에서 보기만 해도 그 사람 브라우저에서 코드가 실행됨. 알림창 대신 쿠키를 훔쳐 보내는 코드였으면 계정 넘어감.
화면엔 삭제 버튼이 없었는데 왜 삭제됐을까요? 이 문제를 어디서 막아야 할까요?
→ 서버에서 사용자 역할을 확인 · DB의 접근 레벨과 역할을 비교 · 실패한 시도도 감사 로그에 남긴다.
해킹 타임 2 · SSRF와 방어 설계
t-box의 “URL로 파일 가져오기” 기능을 공격해, 서버 안의 진짜 파일을 URL 한 줄로 꺼내 보는 걸 직접 확인함.
충님의 설명 ›
t-box에는 URL을 넣으면 서버가 그 주소로 접속해 내용을 가져오는 기능이 있습니다. 이걸 이렇게 생각해보세요 — 서버는 “뭐든 가져다주는 심부름꾼”입니다. 그런데 이 심부름꾼은 사장실·금고에도 들어갈 수 있어요. 외부인인 내가 못 가는 곳을, 서버를 시켜서 대신 가져오게 만드는 것 — 이게 SSRF입니다.
내 노트북에서 file:///etc/passwd를 열면 내 파일이 열립니다. 하지만 서버에게 그 주소를 던지면 서버의 파일이 열려요. 지금부터 그걸 직접 해봅니다.
t-box 아래쪽 “URL로 파일 가져오기” 칸에 아래 주소를 붙여넣고, 검사 방식을 취약한 검사로 두고 검사를 눌러봄.
file:///etc/passwd허용됨 ✅ 검증 없이 서버가 그대로 가져옴
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
postgres:x:114:120:PostgreSQL admin:/var/lib/postgresql:...
… (이하 생략)
- !이건 서버 안에 있는 진짜 파일임. 리눅스 계정 목록이 통째로 털린 거예요. 내 노트북에선 절대 못 보는 남의 서버 내부 파일을, URL 한 줄로 꺼냈음.
이번엔 검사 방식을 방어된 검사로 바꾸고 같은 주소로 다시 검사 눌러봄.
차단됨 ⛔ http/https가 아니라서 거부 — 파일 내용이 안 나옴
- ✓같은 주소인데 방어된 검사는 아무것도 안 내줌. 차이는 딱 하나 — 서버가 주소를 검사하느냐 안 하느냐임.
여유 되면 http://169.254.169.254/latest/meta-data(클라우드 서버라면 관리자 키가 나오는 주소)나 아래 표의 다른 내부 주소도 취약한 검사로 넣어봄.
| URL | 판정 |
|---|---|
| https://example.com/report.pdf | 허용 |
| http://localhost/admin | 차단 |
| http://127.0.0.1:3000 | 차단 |
| http://0.0.0.0:3000 | 차단 |
| http://10.0.0.5/secret | 차단 |
| http://172.16.0.10/secret | 차단 |
| http://192.168.0.10/secret | 차단 |
| http://169.254.169.254/latest/meta-data | 차단 |
| file:///etc/passwd | 차단 |
| ftp://example.com/file.txt | 차단 |
숙제로 만들 제대로 된 t-box는 아래처럼 막아야 함. 지금 앱의 “방어된 검사”가 이걸 하고 있음.
- http/https만 허용
- DNS 해석 후 IP 검사 · 사설 IP·localhost·link-local 차단
- 리다이렉트 후 최종 주소 재검사
- 요청 시간 제한 · 응답 크기 제한
- 차단 이벤트를 감사 로그에 기록
왜 이렇게 쉽게 뚫렸을까 · 제대로 된 서비스란
방금 부순 걸 정리함. “그럼 제대로 만들려면 뭐가 달라야 하나”를 짚고, 다음 단계에서 설계로 옮김.
| 무엇이 뚫렸나 | 진짜 원인 | 제대로라면 |
|---|---|---|
| 권한 없이 파일 삭제 | 화면에서 버튼만 숨기고 서버는 검사 안 함 | 서버가 요청자의 역할을 확인 |
| 숨긴 파일이 다 보임 | 서버가 모든 파일을 내려주고 화면에서만 필터 | 권한 없는 데이터는 애초에 안 내려줌 |
| 파일명이 코드로 실행(XSS) | 입력값을 그대로 화면에 출력 | 출력할 때 글자로 안전하게 이스케이프 |
| 내부 주소 접근(SSRF) | 사용자가 준 URL을 검증 없이 서버가 요청 | http/https만·사설IP 차단·최종주소 재검사 |
| 누가 뭘 했는지 모름 | 기록(감사 로그)이 아예 없음 | 주요 행동·차단 이벤트를 로그로 남김 |
화면에서 버튼을 숨기는 것은 보안이 아니다. 서버가 권한을 확인해야 보안이다.
충님의 설명 ›
방금 우리가 한 공격은 대단한 기술이 아니었어요. 대부분 클릭 몇 번, 주소 하나였습니다. 그런데도 파일이 지워지고, 남의 자료가 보이고, 코드가 실행됐죠. 이게 보안을 나중으로 미룬 서비스의 실제 모습입니다.
공통점이 하나 있어요. “화면에서 막으면 되겠지”라고 생각한 겁니다. 하지만 화면은 사용자 손 안에 있어요. 진짜 방어선은 서버입니다. 그리고 방어는 기능을 만들 때 같이 넣어야지, 다 만든 뒤에 얹으려면 이미 늦습니다.
좋은 서비스는 “되게 만드는 것”에서 끝나지 않습니다. “나쁘게 쓰려는 사람”까지 생각하는 것입니다.
제대로 만들려면 · PRD와 아키텍처를 AI와 설계
방금 겪은 취약점이 처음부터 안 생기게, 무엇을 만들지(PRD)와 어떻게 만들지(아키텍처)를 AI와 상의해 문서로 남김. 이 문서가 숙제 출발점임.
충님의 설명 ›
많은 사람이 AI에게 바로 “앱 만들어줘”라고 합니다. 그러면 방금 본 것처럼 보안이 빠진 게 나올 수도 있어요. 그래서 만들기 전에 무엇을·어떻게 만들지 먼저 정리합니다 — 그게 PRD와 아키텍처예요.
핵심은 보안을 요구사항에 처음부터 적어 넣는 겁니다. “권한은 서버에서 확인”, “입력값은 안전하게 출력”, “주요 행동은 로그로” 같은 걸 PRD에 못 박아두면, AI도 그에 맞춰 만들어요.
그리고 프롬프트에서 “적절히·안전하게 같은 모호한 말을 쓰지 말고 측정 가능한 조건으로 써라”, “각 요구사항에 ID를 붙이고, 설계가 그 ID를 어떻게 만족하는지 추적성을 표시해라”처럼 작성 규칙까지 지시하면, 목차만 채운 문서가 아니라 실제로 개발팀에 넘길 수 있는 문서가 나옵니다. 아래 프롬프트가 그렇게 짜여 있어요.
좋은 바이브 코딩은 구현 요청 전에 설계 대화를 먼저 합니다. 그리고 그 결과를 문서로 남겨 계속 참조합니다.
[역할] 너는 B2B SaaS를 여러 번 출시한 시니어 프로덕트 매니저다.
[과제] 사내 파일 공유 서비스 "t-box"의 PRD를 실제 개발팀에 넘길 수 있는
수준으로 작성한다. 나는 방금 이 서비스의 "보안을 고려하지 않은 버전"을
직접 공격해봤고, 이번엔 처음부터 제대로 정의하려 한다.
[작성 원칙 — 반드시 지킬 것]
- 모호어 금지: "적절히", "안전하게", "빠르게", "필요시" 같은 말은 쓰지 말고
전부 측정 가능한 수치·조건으로 바꿔 써라. (예: "빠르게" → "p95 < 300ms")
- 모든 기능 요구사항에는 고유 ID(FR-01…)와 우선순위(P0/P1/P2)를 붙여라.
- 모든 유저 스토리에는 Given/When/Then 형식의 인수조건을 최소 2개씩 달아라.
- 각 요구사항은 "구현했는지 테스트로 확인 가능한가?"를 통과해야 한다.
통과 못 하면 다시 써라.
- 표가 명확한 곳(권한 매트릭스, 접근 레벨, 마일스톤)은 마크다운 표로 써라.
- 근거 없는 숫자를 지어내지 말고, 가정은 "가정:"으로 명시하고 근거를 붙여라.
[분량/형식] 마크다운. 각 섹션에 번호. 최소 이 정도 깊이로:
1. 문서 정보 — 버전, 작성일(가정), 상태, 용어 정의(Glossary)
2. 개요 — 1줄 설명 / 해결할 문제(현재의 불편을 구체 시나리오로) /
목표를 측정지표로(예: "공유 요청 처리 시간 X분 → Y초") / Non-goals 명시
3. 페르소나 — Admin / Manager / Employee / Guest 각각의 목표·권한·불안요소
4. 유저 스토리 & 인수조건 — 역할별로 총 12개 이상, 각 스토리에
"As a / I want / So that" + Given/When/Then 인수조건 2개 이상
5. 기능 요구사항 — FR-ID·우선순위 포함. 최소 다음을 다뤄라:
업로드(재개/중복/크기제한), 목록(검색·정렬·페이지네이션·필터),
미리보기/다운로드, 삭제(휴지통/영구), 공유(링크·만료·접근레벨 변경)
6. 권한 모델 — 역할 4종 × 행동(업로드/조회/다운로드/공유/삭제/관리)의
권한 매트릭스 표 + 접근 레벨(public/internal/team/admin-only) 정의와
"누가 무엇을 볼 수 있는가" 규칙을 문장으로 못 박기
7. 보안 요구사항 — 각 항목을 검증 가능한 요구문으로(SR-ID 부여):
서버측 인증·인가, 권한 없는 데이터는 응답에서 원천 제외,
출력 인코딩(XSS)·CSRF 토큰, 업로드 크기/확장자/MIME 검증 및
추측 불가 저장명, SSRF 방어(스킴 화이트리스트·사설망 차단·리다이렉트 재검사),
전 구간 감사 로그, 세션·비밀번호·전송(TLS) 정책
8. 비기능 요구사항 — 성능(동시 사용자·파일 수 가정과 p95 목표),
확장성, 가용성(SLO), 관측성(로그·지표·알림), 접근성(WCAG), 국제화
9. 데이터 모델 개요 — 엔티티(User, File, Permission/ACL, AuditLog, Session)와
핵심 필드·관계
10. 데이터 수명주기 & 보관 정책 — 파일/로그/세션별 보관 기간(리텐션),
삭제 방식(소프트 삭제 → 휴지통 → 영구 파기), 파기 시 백업본 처리,
개인정보/민감정보 취급 원칙
11. 백업·복구·비즈니스 연속성 (필수) — 다음을 수치로 정의:
- RPO(허용 데이터 손실 시간)와 RTO(목표 복구 시간)를 정하고 근거 제시
- 백업 대상(DB / 업로드 파일 / 설정·시크릿)별 주기·방식(전체/증분)·
보관 세대수·보관 위치(오프사이트 포함)
- 백업 암호화 및 접근 통제(백업본도 유출 자산이라는 관점)
- 복구 절차(런북)와 "복구 훈련을 언제/어떻게 검증할지"
- 랜섬웨어·실수 삭제·DB 손상 각 시나리오별 대응
12. 감사 로그 명세 — 어떤 이벤트를(성공·실패·차단) 어떤 필드로 남길지 표.
로그 보관 기간, 로그에 민감정보를 남기지 않는 규칙, 위·변조 방지
13. 운영 — 모니터링 지표와 알림 임계값, 장애 등급/에스컬레이션,
정기 점검 항목, 배포·롤백 전략
14. 릴리스 계획 — 마일스톤(M1 MVP / M2 보안하드닝 / M3 성능·운영)별
포함 FR-ID와 완료 정의(Definition of Done)
15. 성공 지표 — 활성 사용자, 업로드 성공률, 권한 위반 차단 건수,
백업 성공률·복구 훈련 통과율 등
16. 리스크·의존성·미해결 질문(Open Questions)
마지막에 "이 PRD가 처음의 취약한 버전과 무엇이 달라졌는지" 3줄 요약.
전체를 PRD.md 파일로 저장해줘.
[역할] 너는 t-box를 실제로 구현할 시니어 백엔드 엔지니어이자
보안 리뷰까지 하는 테크리드다.
[과제] 방금 만든 PRD.md를 읽고, 그 요구사항(FR-/SR- ID)을 만족하는
아키텍처 설계 문서를 작성한다. 이 문서만 보고 다른 개발자가
동일하게 구현할 수 있어야 한다.
[제약]
- 스택: 순수 PHP(프레임워크 없이) + PostgreSQL + nginx + php-fpm,
파일은 서버 디스크 저장. 도메인 "내이메일앞자리.tla.so".
- 새 요구사항을 지어내지 말고, 각 설계 결정이 PRD의 어느 FR-/SR-를
만족시키는지 괄호로 추적성(traceability)을 표시해라.
- 설계 결정에는 이유와 대안을 짧게 남겨라(왜 이 방식? 안 쓴 대안은?).
- 다이어그램은 mermaid 코드블록으로 그려라(렌더 가능해야 함).
[포함할 내용]
1. 아키텍처 개요 — 시스템 컨텍스트 다이어그램(mermaid),
구성요소별 책임(브라우저 / nginx / php-fpm / PHP 앱 계층 /
PostgreSQL / 파일 저장소)과 신뢰 경계(trust boundary) 표시
2. 요청 시퀀스 — 업로드 / 목록 / 다운로드 / 삭제 / 공유 각각을
mermaid sequenceDiagram으로. 각 시퀀스에 "인증 확인 → 인가(역할×접근레벨)
확인 → 실행 → 감사 로그" 단계를 명시하고, 인가 실패 시 403 분기까지
3. 애플리케이션 계층 구조 — 요청이 통과하는 계층(라우팅 → 입력검증 →
인증 미들웨어 → 인가 검사 → 도메인 로직 → 데이터 접근 → 출력 인코딩)과
각 계층의 책임. 권한 검사가 "한 곳(서버)"에서만 일어나도록 하는 구조
4. 데이터 모델 — users, files, permissions/ACL, audit_logs, sessions의
DDL 수준 스키마(컬럼·타입·제약·인덱스·FK)와 ER 다이어그램(mermaid).
접근 레벨/역할을 DB에서 표현하는 방식과 권한 조회 쿼리 예시
5. 인가 설계 — 목록 조회 시 "권한 있는 파일만" 내려주는 쿼리 전략,
단건 접근(다운로드/삭제) 시 소유·역할·접근레벨 검사 지점(IDOR 방지)
6. 보안 설계 — 위협 모델을 간단한 표로(자산 / 위협 / 대응).
공격면별 방어 배치: 입력검증·출력 인코딩(XSS)·CSRF·업로드 검증
(크기/확장자/MIME/추측불가 저장명/웹루트 밖 저장)·SSRF 방어·
전송 암호화·세션 관리·비밀정보(.env) 취급
7. API 명세 — 엔드포인트별 경로 · 메서드 · 요청/응답 스키마 ·
필요 권한 · 에러 코드(401/403/404/413/422). 표로
8. 파일 저장 전략 — 저장 경로(웹루트 밖), 저장 파일명 규칙,
다운로드 시 앱을 거쳐 스트리밍하는 이유, 직접 URL 접근 차단
9. 백업·복구 설계 (필수) — PRD의 RPO/RTO를 만족하는 구체적 방법:
- 백업 대상별 전략: PostgreSQL(pg_dump/WAL 아카이빙 중 선택과 이유),
업로드 파일 디렉터리, .env·nginx 설정
- 주기·보관 세대·보관 위치(로컬 + 오프사이트), 백업 파일 암호화 방식
- 백업 자동화(cron 예시)와 성공/실패 알림
- 복구 런북: DB만 손상 / 파일만 손실 / 서버 전체 재구축 각 시나리오별
명령 수준 절차와 예상 소요 시간(RTO와 대조)
- 복구 검증 방법(정기 리허설, 체크섬 비교)
10. 코드 구조 — 실제 폴더/파일 트리와 각 파일 책임(한 줄씩)
11. 배포/운영 — nginx 서버블록 요지(php-fpm 연동, 정적/동적 분리,
.env·.git·백업파일 노출 차단), .env로 관리할 값 목록,
로그 위치·로테이션, 헬스체크 엔드포인트, 배포·롤백 절차
12. 관측성 — 무엇을 로그/지표로 남기고 어떤 조건에 알림을 보낼지
13. 미결정 사항과 향후 확장(용량 증가 시 오브젝트 스토리지 전환 등)
전체를 ARCHITECTURE.md 파일로 저장해줘.
[역할] 너는 침투 테스트와 시큐어 설계 리뷰를 전문으로 하는
애플리케이션 보안 엔지니어(AppSec)다. "통과시켜주는 리뷰"가 아니라
공격자 관점으로 이 설계를 실제로 깨보는 게 목적이다.
[입력] PRD.md 와 ARCHITECTURE.md 를 모두 읽고 시작해라.
[1) 자산·신뢰경계 식별]
보호 자산(파일 원본, 파일 메타데이터, 사용자 계정/세션, 감사 로그,
백업본, .env의 비밀값)을 나열하고, 신뢰 경계(브라우저↔서버, 앱↔DB,
앱↔파일시스템, 운영자 접근)를 표시.
[2) STRIDE 위협 모델링]
각 구성요소·흐름에 Spoofing / Tampering / Repudiation /
Information Disclosure / Denial of Service / Elevation of Privilege
를 적용해 위협을 도출. 표로:
| ID | 자산 | 위협(STRIDE) | 공격 시나리오 | 영향 | 가능성 | 위험도 | 설계의 대응 | 미흡점 |
[3) 내가 실제로 뚫은 4가지 재검증 (반드시)]
프론트 권한 우회 / 권한 없는 데이터 노출 / 저장형 XSS(파일명·설명) /
SSRF(file:// 및 내부망 주소로 서버 내부 파일 유출).
각각 "어느 SR-ID·어느 흐름"이 막는지 명시하고, 우회 가능성을 다시 공격해봐라.
[4) 파일 공유 서비스 특화 위협 — 아래는 전부 점검]
- 접근제어: IDOR(파일 ID 조작), 수평/수직 권한 상승, 공유 링크 추측·만료 우회
- 업로드: 웹셸·실행파일, MIME 스푸핑, 압축폭탄, 경로 조작(../), 심볼릭 링크
- 다운로드: 경로 탐색으로 임의 파일 읽기, 인증 우회 직접 접근
- 인젝션: SQL / OS 커맨드 / 헤더 인젝션, 저장형·반사형 XSS
- 세션/인증: 세션 고정·탈취, CSRF, 브루트포스, 비밀번호·토큰 저장 방식
- SSRF: 리다이렉트 우회, DNS 리바인딩, 클라우드 메타데이터 접근
- 로깅: 민감정보 로깅, 로그 위·변조, 로그 인젝션
- 데이터 보호: 저장/전송 암호화, 백업본 유출, 시크릿(.env) 노출
- 가용성/복구: 백업 무결성, 랜섬웨어·삭제 사고 시 RPO/RTO 실현 가능성
[5) 방어 심층성·규정]
다층 방어(한 겹 뚫려도 다음이 막는지), 최소 권한, 안전한 기본값
(deny by default) 여부. OWASP Top 10 / OWASP ASVS 관점에서 빠진 항목 지적.
[6) 설계 품질]
요구사항 간 충돌·모호함, 빠진 엣지 케이스, 테스트로 검증 불가능한 요구사항.
[출력 형식]
발견마다: 제목 / 심각도(Critical·High·Medium·Low + 근거) /
공격 시나리오(재현 단계) / 영향 / PRD·아키텍처의 어디를 어떻게 고칠지(구체 수정안) /
검증 방법. 심각도 높은 순 정렬. 마지막에 "출시 전 반드시 막아야 할 Top 5".
숙제 · 제대로 된 t-box를 만들어 오기
오늘 만든 PRD.md·ARCHITECTURE.md를 실제 명세로 삼아, 방금 뚫었던 취약점이 없는 파일 공유 서비스를 운영 가능한 수준으로 완성해 옴. AI와 만들되 검증은 내가 함.
| 목표 | PRD/아키텍처를 만족하는, 오늘의 4대 취약점이 없는 t-box를 완성 |
| 스택 | 순수 PHP + PostgreSQL + nginx (프레임워크 없이) |
| 제출물 | Git 서버(git2.tla.so) 내 저장소 — 코드 · README · 보안 자체점검 문서 |
| 방식 | AI와 기능 하나씩 만들고 내가 직접 공격해 검증 후 다음으로. 매 기능 커밋(한글) |
- 1단계 · 뼈대와 DB — 스키마(users·files·permissions·audit_logs·sessions) 생성, 접속·설정을
.env로 분리 - 2단계 · 인증/세션 — 로그인, 세션 관리, 로그인 안 하면 아무것도 못 함
- 3단계 · 기본 기능 — 업로드 / 목록 / 다운로드 / 삭제 (아직 권한 없이 동작만)
- 4단계 · 서버 인가 — 모든 API에 역할×접근레벨 검사, 권한 없으면 403 + 목록·다운로드 응답에서 원천 제외 (IDOR 방지: 남의 파일 ID로도 못 받게)
- 5단계 · 입력/출력 안전 — 출력 인코딩(XSS), CSRF 토큰, SQL은 파라미터 바인딩
- 6단계 · 업로드 하드닝 — 크기·확장자·MIME 검증, 추측 불가 저장명, 웹루트 밖 저장 + 앱 거쳐 다운로드
- 7단계 · SSRF 방어 — (URL 가져오기 기능을 만들었다면) http/https만·사설망 차단·리다이렉트 재검사
- 8단계 · 감사 로그 — 성공/실패/차단 이벤트 기록, Admin만 열람
- 9단계 · 성능/운영 — 목록 검색·정렬·페이지네이션, 백업 스크립트(cron) + 복구 절차 README에
3~8단계는 각각 끝나면 바로 그 취약점을 스스로 공격해보고, 막히는 걸 확인한 뒤 커밋.
내가 만든 PRD.md와 ARCHITECTURE.md를 먼저 읽어줘. 이 문서가 명세야.
t-box를 순수 PHP + PostgreSQL로, 프레임워크 없이 만들 거야.
한 번에 다 만들지 말고 아래 단계 순서로, 각 단계가 끝나면
멈추고 내가 확인·커밋한 뒤 다음으로 넘어가자.
1) DB 스키마 + .env 분리
2) 로그인/세션
3) 업로드·목록·다운로드·삭제(동작만)
4) 서버 인가: 모든 API에 역할×접근레벨 검사(403), 목록·다운로드
응답에서 권한 없는 건 원천 제외, 남의 파일 ID 직접접근(IDOR)도 차단
5) 출력 인코딩(XSS)·CSRF 토큰·SQL 파라미터 바인딩
6) 업로드 검증(크기·확장자·MIME·추측불가 저장명·웹루트 밖 저장)
7) (URL 가져오기 기능이 있으면) SSRF 방어
8) 감사 로그(성공·실패·차단), Admin만 열람
9) 목록 검색·정렬·페이지네이션 + 백업/복구 스크립트
각 단계마다: 무엇을 만들었는지 요약, 내가 확인할 방법,
한글 커밋 메시지 제안을 함께 줘. 지금은 1단계만 시작해.
방금 만든 단계를 내가 직접 공격해서 검증하고 싶어.
이 단계에서 막아야 할 공격을 재현하는 방법을 알려줘 —
브라우저 개발자도구나 콘솔에서 내가 직접 해볼 수 있는 형태로.
그리고 "막히면 이런 결과, 안 막히면 이런 결과"를 미리 알려줘.
막히지 않으면 어느 파일 어느 줄을 어떻게 고쳐야 하는지 짚어줘.
(고치는 건 네가 하지 말고, 내가 읽고 판단해서 반영할게.)
기능
보안 — 직접 공격해서 막히는 걸 증명
운영·제출물
완성 코드를 git2.tla.so의 내 저장소에 push. README(실행법)와 SECURITY.md(4대 공격 + 추가 위협을 어디서 어떻게 막았는지 + 직접 공격해 막힌 증거)를 반드시 포함. 커밋 히스토리로 단계별로 만든 과정이 보여야 함. 저장소·토큰·push 설정은 맨 아래 부록 참고.
마무리 · 오늘 잡은 감각
반나절 만에 리눅스 서버·터미널·Git·AI 에이전트·해킹·설계까지 다 겪음. 뭘 했는지 짚고, 오늘 핵심을 내 말로 정리함.
| 영역 | 오늘 직접 한 것 |
|---|---|
| 리눅스 서버 | 우분투 VM에 접속해 터미널로 작업 · sudo로 관리자 권한 · 폴더 만들고 소유권 변경 · 패키지 설치 |
| 웹 서비스 구조 | 도메인 → DNS → 웹서버(nginx) → 앱 → DB·파일저장소 흐름 이해 · 내 도메인으로 서비스 띄움 |
| Git | 저장소에서 코드 clone · 커밋과 push의 의미 · 토큰 발급과 .env로 비밀값 관리 |
| AI 에이전트 | Claude Code 설치·로그인 · 터미널 2개로 작업 분리 · INSTALL.md를 읽혀 설치를 통째로 위임 · AI가 준 명령을 검토 후 내 손으로 실행 |
| 해킹 체험 | 숨긴 버튼 되살려 삭제 · 권한 없는 자료 노출 확인 · XSS로 코드 실행 · SSRF로 서버 내부 파일 유출 |
| 설계 | PRD(유저스토리·권한매트릭스·보안·백업/RPO·RTO)와 아키텍처를 AI와 작성 · 보안 관점 검토까지 받음 |
개발 경험 거의 없이 시작해서 반나절에 여기까지 옴. 숙제로 남은 건 이 설계를 실제 서비스로 완성하는 것.
충님의 설명 ›
오늘 반나절 만에 꽤 많은 걸 하셨습니다. 리눅스 서버를 만지고, Git을 쓰고, AI에게 설치를 맡기고, 직접 해킹까지 해보고, PRD와 아키텍처를 설계했어요. 개발 경험이 거의 없는 상태에서 여기까지 온 건 충분히 대단한 겁니다.
그런데 여기서 딱 하나만 오해하지 마세요. 오늘 한 건 맛만 본 수준입니다. PRD 쓰고 AI에게 보안 점검받는 건 기본이지 충분조건이 아니에요. 서버 자체 보안, OS와 nginx·PostgreSQL의 취약점, PHP 버전 문제, 아직 패치도 없는 제로데이 — 이런 게 전부 남아 있습니다.
그리고 AI로 개발 속도가 폭발한 만큼, 공격 기법도 똑같이 폭발하고 있습니다. 게다가 대부분의 보안 사고는 털린 줄도 모르는 상태예요. 조용히 빠져나가고 몇 달 뒤에 외부에서 알려줍니다. 그래서 만들고 끝이 아니라 주기적인 점검과 보안 업데이트가 운영 그 자체인 겁니다.
그리고 오늘 왜 설계부터 시작했는지 — 처음 설계가 잘못되면 기능을 붙일수록 누더기가 되고, 그 이음새마다 보안 구멍과 성능 문제가 터집니다. 나중엔 고치지도 버리지도 못하는 상태가 돼요. 설계에 쓴 30분이 나중에 몇 달을 아낍니다.
충님이 지금 만들고 있는 실제 서비스 t-work(약 90% 완성)를 직접 열어서 보여줌. 오늘 실습이 장난감이 아니라 진짜로 서비스를 만드는 방식이라는 걸 눈으로 확인하는 순서.
- CLAUDE.md — AI에게 프로젝트 규칙·컨벤션·주의사항을 미리 알려주는 문서. 이게 있으면 AI가 매번 헤매지 않고 프로젝트 스타일대로 만듦
- 실제 Git 커밋 히스토리 — 기능·버그수정·리팩터링이 어떤 단위로 쌓였는지, 커밋 메시지를 실제로 어떻게 쓰는지
- 실제 PRD·아키텍처 문서 — 오늘 만든 것과 같은 문서가 실무에서 어느 깊이로 쓰이고, 개발 내내 어떻게 참조되는지
PRD 쓰고, 아키텍처 설계하고, AI한테 보안 점검받는 것 — 이건 기본이지 충분조건이 절대 아님. 오늘 다룬 4가지 취약점은 웹 보안의 입구일 뿐임. 실제 서비스를 운영하려면 아래가 전부 남아 있음.
| 오늘 안 다룬 것 | 왜 위험한가 |
|---|---|
| 서버 자체 보안 | 방화벽·SSH 설정·계정 관리·불필요 포트. 앱이 완벽해도 서버가 뚫리면 끝 |
| OS·미들웨어 취약점 | 리눅스·nginx·PostgreSQL에 계속 발견되는 취약점. 업데이트 안 하면 그대로 구멍 |
| 언어·프레임워크 취약점 | PHP 버전 자체의 보안 이슈, 쓰는 라이브러리의 알려진 취약점(공급망) |
| 제로데이 | 아직 패치가 없는 취약점. “최신으로 유지”해도 못 막는 게 있음 |
| 운영 보안 | 비밀값 관리, 접근 권한 회수, 로그 감시, 백업본 보호, 내부자 위협 |
그리고 이것부터 명심해.
- 1AI로 개발 속도가 폭발한 만큼, 공격 기법도 똑같이 폭발하고 있음. 작년에 안전했던 코드가 올해도 안전하다는 보장이 없음.
- 2대부분의 보안 사고는 “털린 줄도 모르는” 상태임. 조용히 데이터가 빠져나가고, 몇 달 뒤에야 외부에서 알려줌. 그래서 감사 로그와 모니터링이 기능보다 중요할 때가 있음.
- 3만들고 땡이 아님. 주기적인 점검과 보안 업데이트는 선택이 아니라 운영 그 자체임. 서비스가 살아있는 한 계속 해야 함.
왜 오늘 설계부터 시작했냐면. 처음 설계가 잘못되면 기능을 붙일수록 누더기 코드가 됨. 그 이음새마다 보안 구멍과 성능 문제가 생기고, 나중엔 고치자니 다 뜯어야 하고 두자니 계속 터지는 상황이 옴. 그때 가서 “처음부터 다시 만들자”는 비용이 제일 비쌈. 설계에 쓴 30분이 나중에 몇 달을 아낌.
AI가 코드를 대신 써주는 시대에, 사람이 할 일은 무엇을 만들지 정하고, 나온 결과를 의심하고 검증하고, 계속 지켜보는 것이다.
부록 · Git 치트시트 & 문제 해결
막히면 여기. 숙제 제출용 Git 준비, 자주 쓰는 명령, 흔한 에러 해결법.
숙제(제대로 된 t-box)를 내 저장소에 올리려면 저장소와 토큰이 필요함.
- git2.tla.so에 로그인 → + → New Repository → 이름
t-box(README 체크 안 함, 빈 저장소) - 프로필 → 설정 → 어플리케이션 → 액세스 토큰 관리 → 새 토큰 → 권한에서 repository = 읽기와 쓰기 → 생성 후 토큰 복사
/var/www/html/.env에 계정·이메일·저장소주소·토큰을 넣고, Claude Code에 아래처럼 설정을 맡기기
/var/www/html/.env 에 GIT_USERNAME, GIT_EMAIL, GIT_REPOSITORY, GIT_TOKEN이 있어.
이 값으로 git을 초기화하고, 이름·이메일을 설정하고,
원격 저장소 origin을 토큰이 포함된 주소로 연결해줘.
.env는 .gitignore에 넣어 커밋되지 않게 해줘.
커밋 메시지는 항상 한글로 제안해줘.
⚠ 토큰은 .env에만. AI 대화창에 토큰 값을 직접 붙여넣지 마.
GIT 자주 쓰는 명령
git status # 변경사항 확인
git add . # 전체 스테이징
git commit -m "메시지" # 저장
git push # 서버로 올리기
git remote -v # 원격 저장소 확인FIX 흔한 에러
- remote origin already exists
git remote set-url origin <URL> - nothing to commit
변경사항 없음 →git status로 확인 - authentication failed
계정·저장소 권한 확인, 토큰 재발급
지금 변경사항에 맞는 Git 커밋 메시지를 추천해줘.
한글로, 짧고 명확하게 3개 제안해줘.
나중에 봐도 무엇을 했는지 알 수 있는 문장으로.