비개발자를 위한 웹 개발 입문 · 기초

웹 개발 전체 지도

웹 서비스가 어떻게 만들어지는지, 코드 없이도 이해하는 첫걸음.

프론트엔드백엔드데이터베이스인프라
비개발자를 위한 웹 개발 입문 · 심화

웹 개발 심화 지도

기초를 넘어 — TypeScript 타입, 인증 흐름, DB 보안, CI/CD까지 실전 개발의 원리를 이해합니다.

TypeScriptServer ComponentsRLSAuth Flow
스크롤
SECTION 00
Overview

전체 구조

모든 웹앱은 이 5개 레이어로 이루어집니다. 위아래로만 통신합니다.

레이어
0
웹앱 구성요소
예시 건수
0
카운트업 데모
배포 속도
0
git push → 반영
사용자
브라우저모바일
화면을 보는 사람
↕ HTTP 요청 / 응답
01프론트엔드
HTML/CSSReactNext.js
화면 담당
↕ API 호출
02백엔드
Next.js APIRoute Handler
로직 담당
↕ SQL 쿼리
03데이터베이스
SupabasePostgreSQL
저장 담당
04인프라
VercelCloudflare
배포·네트워크
핵심 규칙: 프론트엔드는 DB에 직접 접근하지 않습니다. 반드시 API를 거쳐야 합니다.
⚠️ 이 가이드가 다루지 않는 것 (의도적): Java Spring Boot·JPA·Oracle 등 대기업·엔터프라이즈 스택은 이 가이드의 범위 밖입니다. 대기업 백엔드 취업 준비·CS 기초(자료구조·알고리즘·운영체제)·레거시 시스템 유지보수를 목표로 한다면 이 가이드의 방향과 다를 수 있습니다. 이 가이드는 "1인·소규모 팀이 빠르게 서비스를 출시하는 Next.js+Supabase+Vercel 스택"에 최적화되어 있습니다.

개발 환경 셋업 — 처음 시작할 때 깔아야 하는 것들

코드를 작성·실행·배포하려면 컴퓨터에 도구 몇 개가 필요합니다. macOS·Windows 둘 다 가능합니다.

필수 #1
Node.js
JS·TS 코드 실행기. nodenpm 명령어가 함께 설치됨. LTS 버전 권장.
필수 #2
Git
코드 버전 관리. GitHub에 코드 올릴 때 필요.
필수 #3
코드 에디터
VS Code(무료) 또는 Cursor(AI 내장 에디터).
필수 #4
터미널
macOS는 Terminal/iTerm2, Windows는 PowerShell 또는 WSL2.

코드 에디터 vs AI 코딩 도구

도구역할특징
VS Code전통 에디터무료, 가장 많이 쓰임. 확장 프로그램 풍부.
CursorAI 통합 에디터VS Code 기반 + AI 코드 편집/자동완성 내장.
Claude Code터미널 AI 에이전트명령어로 AI가 파일 직접 수정·생성. 자동화에 유리.
GitHub Copilot코드 자동완성VS Code 확장. 코드 한 줄씩 제안.

새 프로젝트 시작 명령어

터미널에 입력
# 1. Next.js 프로젝트 생성 npx create-next-app@latest my-app # 2. 폴더 진입 cd my-app # 3. 개발 서버 실행 (localhost:3000) npm run dev # 4. 브라우저에서 확인 open http://localhost:3000
4줄로 끝: Next.js 공식 명령어가 필요한 설정을 자동으로 다 해줍니다. TypeScript·Tailwind·ESLint 옵션도 셋업 시 선택 가능.

자주 쓰는 명령어 — 처음 외워둘 10개

명령어역할
npm install패키지 설치
npm install 패키지명특정 패키지 추가
npm run dev개발 서버 시작
npm run build배포용 빌드 만들기
git status변경된 파일 확인
git add .모든 변경 선택
git commit -m "메시지"변경 기록 저장
git pushGitHub에 올리기
ls / dir현재 폴더 파일 목록
cd 폴더명폴더 이동
주의: Windows는 ls 대신 dir을 사용합니다. WSL2(Linux 환경)를 설치하면 macOS와 동일한 명령어를 쓸 수 있습니다.

Next.js 파일 구조 — 폴더가 곧 URL

App Router 구조. 폴더를 만들면 URL이 생기고, 특정 파일 이름이 특정 역할을 합니다.

app/ 폴더 구조 = URL 구조
app/ ├── page.tsx → / (홈 페이지) ├── layout.tsx → 공통 레이아웃 (헤더·사이드바) ├── loading.tsx → 로딩 중 표시 ├── error.tsx → 에러 발생 시 표시 ├── not-found.tsx → 404 페이지 ├── dashboard/ │ └── page.tsx → /dashboard ├── reports/ │ ├── page.tsx → /reports (목록) │ └── [id]/ │ └── page.tsx → /reports/123 (상세, id 동적) └── api/ └── users/ └── route.ts → /api/users (API 엔드포인트)
파일명역할언제 만드나
page.tsx해당 URL 페이지 내용새 화면 만들 때마다
layout.tsx하위 페이지 전체를 감싸는 틀공통 헤더·사이드바 필요할 때
loading.tsx데이터 로딩 중 표시Skeleton UI 넣을 때
error.tsx에러 시 대체 화면에러 바운더리 처리할 때
route.tsAPI 엔드포인트 (서버 코드)api/ 폴더 안에만 작성
핵심: "대시보드 페이지 만들어줘"라고 하면 AI는 app/dashboard/page.tsx를 만듭니다. URL과 파일 경로가 1:1이라는 걸 알면 AI 지시가 훨씬 정확해집니다.
Overview · 심화

렌더링과 데이터 흐름

Server / Client 컴포넌트가 어떻게 나뉘고 데이터가 흐르는지 이해합니다.

Server Component
서버에서 실행
DB 직접 접근 가능. 번들 크기 없음. async/await 사용. 기본값.
Client Component
브라우저에서 실행
State·이벤트 핸들러 사용 가능. 파일 최상단 'use client' 필요.
Server vs Client 컴포넌트
// Server Component — DB 직접 조회 가능 async function Page() { const data = await supabase.from('reports').select() return <Table data={data} /> } // Client Component — 상태·이벤트 사용 'use client' function Filter() { const [tab, setTab] = useState('전체') return <button onClick={() => setTab('이번달')}>필터</button> }
언제 dynamic을 쓰나? 사용자마다 다른 데이터를 보여줘야 할 때(대시보드, 마이페이지). 모든 사람에게 같은 내용이면 static이 더 빠릅니다.
Section 00 / 08
SECTION 01
Layer 1 · 브라우저

브라우저가 하는 일

사용자와 서버 사이의 통역사입니다.

1
URL 입력주소창에 URL 입력
2
DNS 변환도메인 → IP 주소 (인터넷 전화번호부)
3
HTTP 요청서버에 "이 페이지 주세요" 전송
4
파일 수신서버가 HTML·CSS·JS 파일 전달
5
화면 렌더링파일 해석 → 사용자에게 화면 출력

전통적 방식 (MPA)
버튼 클릭 → 서버에 새 페이지 요청 → 전체 새로고침 → 깜빡임
현대적 방식 (SPA · React)
바뀐 부분만 계산 → 해당 부분만 업데이트 → 앱처럼 부드러움

클라이언트 vs 서버 — 가장 기본 개념

클라이언트 (Client)
화면을 보는 쪽. 브라우저·모바일 앱.
요청을 보냄.
서버 (Server)
데이터를 가진 쪽. 컴퓨터.
요청 받으면 응답함.
한 문장 요약: 클라이언트가 "이거 주세요" 하면 서버가 "여기요" 하는 관계. 모든 웹앱이 이 구조입니다.

HTTP 요청·응답 구조

클라이언트와 서버가 주고받는 메시지 형식입니다. 4가지 부분으로 구성됩니다.

HTTP 요청 (Request)
POST /api/login HTTP/1.1 ← ① 메서드 + 경로 Host: myapp.com ← ② 헤더 (메타정보) Content-Type: application/json { ← ③ 본문 (Body) "email": "user@example.com", "password": "secret" }
HTTP 응답 (Response)
HTTP/1.1 200 OK ← ④ 상태코드 Content-Type: application/json { "token": "eyJhbGciOi...", "user": { "name": "김민수" } }

JSON — 데이터를 주고받는 공통 형식

JavaScript Object Notation. 사람도 읽을 수 있고 기계도 파싱 가능한 데이터 형식. 웹 API의 표준입니다.

JSON 5가지 자료형
{ "name": "홍길동", ← 문자열 (string) "age": 30, ← 숫자 (number) "isAdmin": true, ← 불리언 (boolean) "hobbies": ["독서", "운동"], ← 배열 (array) "address": { ← 객체 (object) "city": "서울", "zip": "04524" } }
왜 JSON인가: XML 등 다른 형식보다 가볍고, JavaScript에서 그대로 변수로 쓸 수 있습니다. 거의 모든 웹 API가 JSON으로 통신합니다.

에러 메시지 읽는 법 — 바이브코딩에서 가장 자주 막히는 순간

에러는 무서운 게 아니라 "여기 문제야"라고 알려주는 메시지입니다. 패턴을 알면 80%는 바로 원인을 알 수 있습니다.

브라우저 콘솔 에러 — F12 → Console 탭

에러 메시지원인해결 방향
TypeError: Cannot read properties of undefined (reading 'map')데이터가 아직 없는데 map() 호출데이터 로딩 전 조건 처리: data?.map() 또는 로딩 상태 추가
ReferenceError: X is not defined변수나 함수 이름 오타, 또는 import 누락import 문 확인, 이름 대소문자 확인
TypeError: X is not a function함수가 아닌 것을 함수처럼 호출해당 변수의 타입 확인
Uncaught SyntaxError: Unexpected token문법 오류 (괄호·따옴표 미닫힘 등)AI에게 전체 에러 메시지 붙여넣기
CORS policy: No 'Access-Control-Allow-Origin'다른 도메인 API 차단서버에서 CORS 허용 설정 추가
401 Unauthorized인증 토큰 없거나 만료로그인 상태 확인, 토큰 갱신
403 Forbidden권한 없음 (RLS 차단 포함)Supabase RLS 정책 확인
404 Not FoundURL·API 경로 오타Network 탭에서 실제 요청 URL 확인
500 Internal Server Error서버 코드 에러서버 로그 확인 (Vercel 대시보드)

Next.js 빌드·터미널 에러

에러원인해결
Module not found: Can't resolve 'X'패키지 미설치 또는 경로 오타npm install X 또는 import 경로 확인
Hydration failed서버·클라이언트 렌더링 결과 불일치날짜·랜덤 값 등 'use client' 안으로 이동
NEXT_REDIRECT정상 동작 — redirect() 호출 결과에러 아님. 무시해도 됨
Type '...' is not assignable to type '...'TypeScript 타입 불일치에러 줄 전체를 AI에게 전달
Cannot find module '@/...'tsconfig.json paths 설정 문제tsconfig.json의 paths 항목 확인

AI에게 에러 전달하는 템플릿 — 이 형식으로 주면 해결이 빠릅니다

에러 신고 템플릿
다음 에러가 발생했습니다. 원인을 찾아서 수정해줘. [에러 메시지 전체] TypeError: Cannot read properties of undefined (reading 'map') at DashboardPage (app/dashboard/page.tsx:24:18) [어떤 작업을 했을 때] 대시보드 페이지에서 보고서 목록을 불러오려고 했을 때 [기대한 동작] 보고서 목록이 카드 형태로 화면에 표시되어야 함 [관련 코드 — 에러 난 파일] (해당 파일 전체 붙여넣기)
핵심 원칙: 에러 메시지를 요약하거나 번역하지 마세요. 빨간 글씨 전체를 그대로 복사해서 AI에게 주는 것이 가장 빠릅니다. 줄이거나 설명하면 AI가 잘못 파악합니다.

에러 발생 시 4단계 대응

1
F12 열기Console 탭 빨간 에러 확인. Network 탭에서 실패한 요청 확인
2
에러 패턴 파악위 표에서 에러 종류 확인. 원인 추측
3
AI에게 전달템플릿대로 에러 전문 + 관련 코드 붙여넣기
4
수정 후 재확인같은 에러 없어졌는지 확인. 새 에러 발생하면 1단계부터 반복
Layer 1 · 브라우저 · 심화

HTTP 상태코드와 CORS

에러가 나면 가장 먼저 확인해야 할 것들입니다.

코드의미상황
200OK정상 응답
201CreatedPOST 성공, 생성됨
400Bad Request파라미터 오류
401Unauthorized로그인 필요
403Forbidden권한 없음
500Server Error백엔드 코드 에러
CORS 에러 해결
Access to fetch blocked by CORS policy // 해결: API Route에 헤더 추가 return Response.json(data, { headers: { 'Access-Control-Allow-Origin': '*' } })
CORS 에러가 나는 이유: 보안상 브라우저는 다른 도메인의 API를 기본으로 차단합니다. 서버가 명시적으로 "이 도메인은 허용"이라고 알려줘야 합니다.

DevTools — 비개발자가 가장 먼저 익혀야 할 도구

크롬·엣지에서 F12 또는 마우스 우클릭 → "검사"로 엽니다. 4개 탭만 알면 충분합니다.

역할언제 쓰나
ElementsHTML 구조 보기·수정화면 요소가 어떻게 만들어졌나 확인
Console에러 메시지·로그 확인화면이 안 뜰 때 가장 먼저 확인
NetworkAPI 호출 추적데이터가 안 올 때 요청·응답 확인
Application쿠키·로컬스토리지·세션로그인 정보 저장 확인
실전 팁: 개발자에게 "안 돼요"라고 말할 때 Console 탭 빨간 에러를 캡처해서 보내면 해결 속도가 10배 빨라집니다.

브라우저 저장소 — 쿠키 vs localStorage vs sessionStorage

브라우저는 3가지 저장소를 가집니다. 각각 용도가 달라서 잘못 쓰면 보안 문제 또는 데이터 손실이 발생합니다.

항목CookielocalStoragesessionStorage
저장 위치브라우저브라우저브라우저
서버 전송✅ 매 요청마다 자동
유지 기간설정한 만료일영구 (수동 삭제 전까지)탭 닫으면 사라짐
용량~4KB~5-10MB~5-10MB
JS 접근가능 (HttpOnly면 불가)가능가능
주요 용도인증 토큰·세션설정·테마임시 데이터
인증 토큰은 쿠키 (HttpOnly): JS에서 접근 불가능한 HttpOnly 쿠키로 저장하면 XSS 공격으로 토큰 탈취가 불가능합니다. localStorage에 JWT 저장은 XSS에 취약합니다.
Section 01 / 08
SECTION 02
Layer 2 · 프론트엔드

화면을 만드는 법

HTML → CSS → React → Next.js 순서로 쌓입니다.

HTML
구조
"무엇이 있는가" — 버튼, 표, 입력창
CSS / Tailwind
스타일
"어떻게 보이는가" — 색상, 크기, 간격
React
컴포넌트 + 상태
"어떻게 동작하는가" — 클릭·필터·업데이트
Next.js
라우팅 + 서버
"어떻게 연결하는가" — URL·DB·배포

Tailwind CSS — 유틸리티 클래스 방식

스타일을 작성하는 두 가지 방식이 있습니다. Tailwind는 미리 만들어진 클래스를 HTML에 직접 조합하는 방식입니다.

전통적 CSS
별도 파일에 스타일 작성. 클래스 이름 고민 필요.
.my-button { padding: 8px 16px; }
Tailwind CSS
HTML에 미리 정의된 유틸리티 클래스 조합.
<button class="px-4 py-2">
왜 인기 있나: 클래스 이름 고민 불필요. HTML만 봐도 어떻게 보일지 짐작 가능. shadcn/ui 같은 컴포넌트 라이브러리도 모두 Tailwind 기반입니다.

shadcn/ui — 미리 만들어진 부품 모음

Tailwind로 손수 만들기에는 시간이 오래 걸리는 버튼·카드·테이블·모달을 미리 조립해둔 라이브러리입니다.

직접 만들기 (Tailwind만)
클래스 10개 이상 조합 필요.
<button class="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600 focus:ring-2 ...">
shadcn/ui 사용
한 줄로 끝.
<Button>저장</Button>
일반 라이브러리와의 차이: npm install이 아니라 코드를 내 프로젝트에 직접 복사합니다. 그래서 자유롭게 수정 가능, 버전 충돌 없음. 디자인 규칙(border-radius·padding 등)도 직접 코드 안에서 수정할 수 있습니다.

폼 (Form) — 가장 흔한 UI 패턴

사용자 입력을 받는 모든 요소. 로그인·검색·등록·댓글 등 거의 모든 화면에 있습니다.

React 폼 기본
const [name, setName] = useState('') return ( <form onSubmit={handleSubmit}> <input value={name} onChange={e => setName(e.target.value)} /> <button type="submit">전송</button> </form> )
폼 처리 4단계: 입력 받기 → 검증 → 서버 전송 → 결과 표시. 검증·에러 처리 때문에 폼이 생각보다 어렵습니다. 그래서 react-hook-form 같은 라이브러리를 씁니다.

JavaScript 기본 문법 — 코드를 읽기 위한 최소

변수·함수·조건문·반복문 4가지만 알면 대부분의 코드를 읽을 수 있습니다.

변수 — 값에 이름 붙이기
const name = '홍길동' // 변하지 않는 값 (상수) let count = 0 // 나중에 바뀔 수 있는 값 // 자료형 5가지 const str = '문자열' // string const num = 42 // number const ok = true // boolean const arr = [1, 2, 3] // array (배열) const obj = { name: '민수' } // object (객체)
함수 — 재사용 가능한 코드 묶음
// 일반 함수 function add(a, b) { return a + b } add(2, 3) // → 5 // 화살표 함수 (현대 표기) const double = (n) => n * 2 double(5) // → 10
조건문 · 반복문
// 조건문 (if) if (score >= 90) { result = 'A' } else if (score >= 80) { result = 'B' } else { result = 'C' } // 반복문 — 배열 처리에 가장 흔함 [1, 2, 3].map(n => n * 2) // → [2, 4, 6] [1, 2, 3].filter(n => n > 1) // → [2, 3] [1, 2, 3].forEach(n => console.log(n))

async / await — 비동기 처리

서버 응답이나 파일 읽기처럼 "시간이 걸리는 작업"을 자연스럽게 쓰는 문법입니다.

서버에서 데이터 가져오기
async function getUser() { const response = await fetch('/api/user') // 응답 대기 const data = await response.json() // JSON 파싱 대기 return data }
핵심: async는 "이 함수 안에 기다리는 게 있다"는 표시, await는 "끝날 때까지 기다려" 명령. 이 두 키워드로 비동기 코드가 일반 코드처럼 보이게 됩니다.

import / export — AI 코드 첫 줄 읽기

AI가 만든 거의 모든 파일은 import로 시작합니다. 패턴을 알면 코드가 훨씬 읽기 쉽습니다.

import / export 패턴
// 다른 파일에서 가져오기 import React from 'react' // 기본값 가져오기 import { useState, useEffect } from 'react' // 이름으로 가져오기 import { Button } from '@/components/ui/button' // 내 파일 가져오기 // 내보내기 — 다른 파일이 쓸 수 있게 export default function Page() { // 기본 내보내기 (파일당 1개) return <div>내용</div> } export const helper = () => {} // 이름 내보내기 (여러 개 가능)
에러 "Module not found" 원인: import 경로 오타 또는 미설치 패키지. npm install 패키지명으로 해결.

React 핵심 개념 3가지

한 번 만들면 어디서나 재사용하는 화면 부품입니다.
KPICard 컴포넌트
function KPICard({ 제목, 값, 단위 }) { return <div><h2>{값}{단위}</h2></div> } <KPICard 제목="건수" 값={42} 단위="건" /> <KPICard 제목="인원" 값={18} 단위="명" />
화면이 기억하는 값. 바뀌면 화면이 자동으로 따라 바뀝니다.
State 예시
const [탭, set탭] = useState('전체') // 탭 클릭 시 set탭('이번달') React가 자동으로 목록 다시 그림
컴포넌트에 데이터를 전달하는 방법입니다.
Props 예시
<KPICard 제목='총 건수' ← props 값={42} ← props 색상='blue' ← props />

Skeleton UI — 로딩 상태

Skeleton UI 데모
42
총 건수
18
관련 인원
3.2%
발생률
Layer 2 · 프론트엔드 · 심화

TypeScript와 Hooks

실제 프로덕션에서 사용하는 패턴들입니다.

타입을 정의하면 Claude Code가 훨씬 정확한 코드를 작성합니다.
TypeScript 타입
type Report = { id: number date: string dept: string status: '완료' | '진행중' } function Card({ report }: { report: Report }) { return <div>{report.dept} — {report.status}</div> }
컴포넌트 생성/데이터 변경 시 실행되는 코드입니다.
useEffect
useEffect(() => { fetch() }, []) ← 처음 한 번만 useEffect(() => { fetch(dept) }, [dept]) ← dept 바뀔 때마다
반복되는 로직을 함수로 묶어 재사용합니다.
커스텀 Hook
function useReports(dept) { const [data, setData] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { fetchReports(dept).then(setData) }, [dept]) return { data, loading } } // 사용 const { data, loading } = useReports('서울팀')
커스텀 Hook의 장점: 같은 데이터 로딩 로직을 여러 컴포넌트에서 쓸 때 중복 코드가 없어집니다. 수정할 때도 한 곳만 고치면 됩니다.

반응형 디자인 — 모바일 우선 (Mobile-First)

한 코드로 PC·태블릿·모바일 모두 대응하는 방식. 화면 너비에 따라 레이아웃이 자동으로 바뀝니다.

브레이크포인트너비대상 기기
기본 (no prefix)~ 640px모바일
sm:640px ~큰 모바일·작은 태블릿
md:768px ~태블릿
lg:1024px ~노트북
xl:1280px ~데스크톱
Tailwind 반응형 예시
// 모바일: 1열, 태블릿: 2열, 노트북: 3열 <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3"> // 모바일: 16px, 데스크톱: 32px <h1 class="text-base lg:text-2xl"> // 모바일에서만 숨김 <div class="hidden md:block">
모바일 우선 원칙: 작은 화면부터 디자인하고 점점 키워나갑니다. 반대로 하면 모바일에서 깨지기 쉽습니다. 사용자의 70%+가 모바일이라면 더더욱.

접근성 (a11y) — 모두가 쓸 수 있는 UI

시각장애·색맹·키보드만 사용하는 사람도 쓸 수 있어야 합니다. 공공기관·B2B 서비스는 법적 요구사항이기도 합니다.

원칙구현 방법
색 + 텍스트 + 아이콘 3중 표기상태를 색으로만 표현 금지. "완료 ✓", "대기 ⏱" 같이 항상 텍스트·아이콘 동반
키보드 네비게이션모든 버튼·링크가 Tab으로 접근 가능. 포커스 표시(focus:ring) 유지
스크린리더 지원아이콘 버튼에 aria-label, 이미지에 alt 텍스트 작성
대비비 4.5:1 이상회색 글씨를 너무 연하게 하지 않기. WCAG AA 기준 준수
터치 영역 44px 이상모바일에서 버튼이 손가락보다 작으면 잘못 누름
접근성 좋은 버튼 예시
// ❌ 색으로만 상태 표시 <div class="text-red-500">실패</div> // ✅ 색 + 아이콘 + 텍스트 <div class="text-red-500 flex gap-1"> <XIcon aria-hidden="true" /> <span>실패</span> </div> // ✅ 아이콘만 있는 버튼은 aria-label <button aria-label="삭제"> <TrashIcon /> </button>

성능 최적화 — 빠른 화면

사용자가 페이지 로딩 3초 이상 기다리면 절반이 이탈합니다. 모바일에서는 더 짧습니다. 최적화는 옵션이 아닙니다.

기법효과구현
이미지 최적화용량 70%↓Next.js <Image> 사용 (자동 WebP·lazy load)
코드 분할초기 로딩↓dynamic()으로 무거운 컴포넌트 lazy load
폰트 최적화FOIT 제거next/font로 폰트 자동 호스팅·preload
캐싱재방문↑SSG·ISR로 정적 페이지 캐시, CDN 활용
번들 크기 감소모바일↑큰 라이브러리는 tree-shaking 되는지 확인
측정 도구: Chrome DevTools의 Lighthouse로 점수 확인 (Performance·Accessibility·SEO·Best Practices). 모바일 점수 90+를 목표로 합니다.

상태 관리 — 어디에 데이터를 보관할까

컴포넌트 간 데이터 공유 방식은 4가지입니다. 잘못 선택하면 props drilling(부모→자식→자식→자식... 데이터 전달)으로 코드가 복잡해집니다.

방식적합한 경우도구
로컬 State한 컴포넌트 안에서만 쓰는 데이터useState
Context API테마·언어·로그인 정보 (변경 드문 전역 상태)createContext
Zustand자주 바뀌는 전역 상태 (장바구니·필터·선택 항목)npm i zustand
URL State공유 가능해야 하는 상태 (페이지·필터·검색어)useSearchParams
Zustand 기본 패턴
// store/filter.ts — 전역 상태 정의 const useFilterStore = create<{ dept: string setDept: (d: string) => void }>((set) => ({ dept: '전체', setDept: (d) => set({ dept: d }), })) // 어떤 컴포넌트에서든 바로 사용 const { dept, setDept } = useFilterStore()
선택 기준 한 줄: URL에 있어도 되면 URL 상태, 로그인 정보처럼 전역이지만 변경 드물면 Context, 자주 바뀌는 전역이면 Zustand, 그 외엔 useState.

데이터 페칭 패턴 — 서버 데이터를 스마트하게

단순 fetch는 캐시가 없어서 같은 데이터를 반복 요청하고, 탭 이동 시 재갱신도 안 됩니다. TanStack Query가 표준입니다.

단순 fetch (문제)
캐시 없음 → 매번 서버 요청
탭 이동 시 데이터 stale
로딩/에러 직접 관리
동일 데이터 중복 요청
TanStack Query (해결)
자동 캐싱 + 백그라운드 갱신
탭 포커스 시 자동 refetch
로딩·에러 상태 자동 관리
낙관적 업데이트 지원
TanStack Query 기본 패턴
// 데이터 조회 const { data, isLoading, error } = useQuery({ queryKey: ['reports', dept], ← dept 바뀌면 자동 refetch queryFn: () => fetchReports(dept), staleTime: 1000 * 60 * 5 ← 5분 캐시 }) // 데이터 수정 (저장 버튼 등) const mutation = useMutation({ mutationFn: saveReport, onSuccess: () => queryClient.invalidateQueries(['reports']) ↑ 저장 후 목록 자동 갱신 })

폼 검증 — react-hook-form + zod

입력값 검증은 직접 짜면 코드가 금세 복잡해집니다. react-hook-form(폼 상태)과 zod(스키마 검증)가 표준 조합입니다.

zod 스키마 + react-hook-form
// 1. 검증 규칙 정의 (zod) const schema = z.object({ name: z.string().min(2, '이름은 2자 이상'), email: z.string().email('이메일 형식 오류'), dept: z.enum(['서울', '부산', '대전']), }) // 2. 폼에 연결 (react-hook-form) const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(schema) }) // 3. 에러 메시지 표시 <input {...register('email')} /> {errors.email && <p>{errors.email.message}</p>}
왜 이 조합인가: zod는 타입스크립트 타입과 검증 규칙을 한 번에 정의합니다. API에도 동일 스키마를 재사용할 수 있어 프론트·백엔드 검증이 일치됩니다.

에러 바운더리 — 컴포넌트 에러 격리

컴포넌트 하나에서 에러가 나면 React는 기본적으로 페이지 전체를 흰 화면으로 만듭니다. Error Boundary가 이걸 차단합니다.

바운더리 없음
차트 컴포넌트 1개 에러
→ 페이지 전체 흰 화면
→ 사용자는 무슨 일인지 모름
바운더리 있음
차트만 "오류 발생, 재시도" 표시
→ 다른 영역은 정상 동작
→ 사용자가 일부 기능 계속 사용
Next.js error.tsx 파일 (자동 적용)
// app/dashboard/error.tsx 'use client' export default function Error({ error, reset }) { return ( <div> <h2>문제가 발생했습니다</h2> <p>{error.message}</p> <button onClick={reset}>다시 시도</button> </div> ) }
Next.js 자동 처리: 폴더에 error.tsx를 만들면 그 폴더 안의 모든 컴포넌트 에러를 자동 캐치합니다. 별도 설정 불필요.
Section 02 / 08
SECTION 03
Layer 3 · 백엔드

API란 무엇인가

HTTP 규칙은 어떤 언어·프레임워크든 동일합니다. 사용하는 도구만 다릅니다.

메서드의미예시
GET주세요목록 조회
POST추가해주세요새 항목 등록
PUT바꿔주세요내용 수정
DELETE지워주세요기록 삭제
Next.js API 구조
app/api/ ├─ reports/route.ts ← GET·POST ├─ reports/[id]/route.ts ← GET·PUT·DELETE └─ users/route.ts ← GET·POST
Flask API 구조 (Python)
# routes/parking.py — Flask 라우트 방식 @app.route('/dashboard') def dashboard(): records = db.query('SELECT * FROM reports') return render_template('dashboard.html', records=records) @app.route('/register', methods=['POST']) def register(): data = request.form db.insert(data) return redirect('/dashboard')
같은 개념, 다른 언어: Next.js의 route.ts와 Flask의 @app.route()는 모두 같은 HTTP 규칙(GET/POST/PUT/DELETE)을 따릅니다. 언어만 다릅니다.

JSON — API의 공통 언어

서버와 브라우저가 데이터를 주고받을 때 쓰는 형식. 거의 모든 API가 이 형식을 사용합니다.

JSON 형식 예시
{ "id": 1, "name": "김민수", "dept": "서울팀", "reports": [ { "date": "2026-01-05", "type": "A" }, { "date": "2026-01-12", "type": "B" } ] }
왜 JSON이 표준이 됐나: 사람이 읽기 쉽고 (XML보다 간단), 모든 프로그래밍 언어가 이해할 수 있기 때문입니다. JavaScript 객체 표기법에서 유래했습니다.

REST API
URL로 리소스를 표현. 가장 많이 쓰이는 방식.
GET /api/reports?dept=서울팀
GraphQL
필요한 데이터만 골라서 요청. 복잡한 관계 데이터에 유리.
query { reports(dept: "서울팀") { id, date } }

API 테스트 도구 — Postman·Bruno

화면 없이 API를 직접 호출해서 응답을 확인하는 GUI 도구입니다. AI가 만든 API 엔드포인트가 실제로 작동하는지 확인하거나, 외부 API를 탐색할 때 필수입니다.

도구특징추천 대상
Postman가장 널리 쓰임. GUI 친화적. 팀 협업 지원. 무료 플랜 있음처음 API 테스트 시작하는 사람
Bruno오픈소스. 모든 데이터가 로컬 파일로 저장됨. Git으로 관리 가능프라이버시가 중요하거나 팀에서 API 모음 공유할 때
Thunder ClientVS Code·Cursor 확장. 에디터 안에서 바로 테스트 가능Claude Code·Cursor 사용자 (별도 앱 설치 불필요)
Postman으로 API 테스트하는 법 (3단계)
# 1. 새 Request 생성 Method: POST URL: http://localhost:3000/api/reports # 2. Body 탭 → raw → JSON 선택 후 데이터 입력 { "dept": "서울팀", "type": "부상", "date": "2026-05-26" } # 3. Send 버튼 클릭 → 오른쪽에 서버 응답 확인 200 OK { "id": 1, "success": true } # 에러면 상태 코드(401/403/500)와 메시지 확인 후 AI에게 전달
AI에게 API 테스트 지시하기: "이 API 엔드포인트를 Postman으로 테스트할 수 있는 예시 요청(Method, URL, Headers, Body)을 알려줘"라고 하면 AI가 바로 Postman에 붙여넣을 수 있는 형태로 줍니다.
Layer 3 · 백엔드 · 심화

미들웨어와 에러 핸들링

인증, 권한, 에러 처리 패턴입니다.

인증 + 에러 핸들링 패턴
export async function GET(req) { try { // 1. 인증 확인 const user = await getUser(req) if (!user) return Response.json( { error: '로그인 필요' }, { status: 401 }) // 2. 파라미터 파싱 const dept = new URL(req.url).searchParams.get('dept') // 3. DB 조회 const { data, error } = await supabase .from('reports').select().eq('dept', dept) if (error) throw error return Response.json({ data }) } catch (e) { return Response.json( { error: '서버 오류' }, { status: 500 }) } }
왜 서버에서 인증을 확인하나? 브라우저 코드(프론트)는 사용자가 직접 수정할 수 있습니다. 진짜 보안은 반드시 서버(백엔드)에서 확인해야 합니다.

AI 통합 — LLM을 백엔드에 연결

웹앱에 챗봇·자동 요약·문서 생성 같은 AI 기능을 넣는 표준 방식입니다. API Route에서 LLM을 호출하는 구조입니다.

주요 LLM API

서비스모델특징
AnthropicClaude긴 문서·코드·분석 강함. 한국어 우수.
OpenAIGPT-4, GPT-5가장 보편적. 이미지·음성도 지원.
GoogleGemini긴 컨텍스트(1M+ 토큰). 멀티모달 강함.
AWS Bedrock다중 모델여러 모델 한 API. 기업 환경 보안.
Next.js API Route에서 Claude 호출
// app/api/summarize/route.ts import Anthropic from '@anthropic-ai/sdk' const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }) export async function POST(req) { const { text } = await req.json() const msg = await client.messages.create({ model: 'claude-opus-4-7', max_tokens: 1024, messages: [{ role: 'user', content: `다음을 3줄로 요약: ${text}` }] }) return Response.json({ summary: msg.content[0].text }) }

RAG — 내 문서를 AI에게 학습시키기

Retrieval Augmented Generation. LLM은 회사 내부 문서를 모릅니다. 질문할 때 관련 문서를 함께 보내면 정확한 답변을 받을 수 있습니다.

RAG 흐름
1. 문서를 작은 조각(chunks)으로 자름 2. 각 조각을 벡터(embedding)로 변환 → Vector DB 저장 (Supabase pgvector, Pinecone, Weaviate 등) 3. 사용자 질문도 벡터로 변환 4. 비슷한 조각 N개를 DB에서 검색 5. 검색된 조각 + 질문을 LLM에 함께 전달 6. LLM이 그 정보 기반으로 답변
왜 RAG가 필요한가: LLM은 학습 시점 이후 정보를 모릅니다. 사내 매뉴얼·법령·정책 같은 비공개 정보도 모릅니다. RAG는 이런 한계를 우회하는 표준 패턴입니다.

스트리밍 응답

LLM 응답은 길어서 한 번에 다 받으면 사용자가 답답합니다. ChatGPT처럼 한 글자씩 흘러나오게 하는 게 표준입니다.

구현: API Route를 ReadableStream 으로 반환하고 프론트에서 response.body.getReader()로 chunk 단위로 받습니다. Vercel AI SDK(@ai-sdk/react)를 쓰면 5줄로 구현됩니다.

실시간 통신 — 데이터가 바뀌면 즉시 반영

일반 HTTP는 클라이언트가 요청해야만 응답합니다. 실시간 알림·채팅·대시보드에는 서버가 먼저 보내는 방식이 필요합니다.

방식특징적합한 경우
PollingN초마다 GET 요청단순, 실시간성 낮아도 됨. 서버 부하 발생.
SSE서버 → 클라이언트 단방향알림·로그 스트리밍. HTTP 그대로 사용.
WebSocket양방향 연결 유지채팅·협업 도구. 실시간성 최고.
Supabase RealtimeDB 변경 즉시 브라우저 반영DB 기반 실시간 대시보드. 가장 쉬움.
Supabase Realtime — DB 변경 구독
// reports 테이블에 새 행 추가되면 자동 반영 useEffect(() => { const channel = supabase .channel('reports') .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'reports' }, (payload) => { setReports(prev => [...prev, payload.new]) }) .subscribe() return () => supabase.removeChannel(channel) }, [])

파일 업로드 — 이미지·문서 처리

파일은 DB가 아닌 전용 스토리지에 저장하고, DB엔 URL만 보관합니다. 두 가지 방식이 있습니다.

방식 A: 서버 경유
브라우저 → API Route → Supabase Storage
서버에서 파일 검증·압축 후 업로드. 안전.
방식 B: Presigned URL
브라우저 → S3/Supabase 직접 업로드
서버 부하 없음. 대용량에 유리. URL은 1회용.
Supabase Storage 업로드
// 1. 파일 업로드 const { data, error } = await supabase.storage .from('documents') .upload(`reports/${Date.now()}.pdf`, file, { contentType: 'application/pdf', upsert: false }) // 2. 공개 URL 얻기 const { data: { publicUrl } } = supabase.storage .from('documents') .getPublicUrl(data.path) // 3. DB에 URL 저장 await supabase.from('reports').insert({ file_url: publicUrl })

이메일·알림 발송

이메일·SMS·카카오 알림은 반드시 API Route(서버)에서 발송합니다. 브라우저에서 직접 발송하면 API 키가 노출됩니다.

서비스용도가격
Resend트랜잭션 이메일무료 3,000건/월
SendGrid대량 이메일무료 100건/일
TwilioSMS$0.0079/건
KakaoTalk Business알림톡~10원/건
Resend로 이메일 발송
// app/api/notify/route.ts import { Resend } from 'resend' const resend = new Resend(process.env.RESEND_API_KEY) await resend.emails.send({ from: '알림 <noreply@myapp.com>', to: 'user@example.com', subject: '새 보고서가 등록됐습니다', html: '<p>확인하러 가기: <a href="...">바로가기</a></p>' })

Cron Job — 정해진 시간에 자동 실행

매일 자정에 리포트 집계, 매주 월요일에 요약 이메일 발송 등 스케줄 작업입니다.

Vercel Cron Jobs (vercel.json)
{ "crons": [ { "path": "/api/cron/weekly-report", "schedule": "0 9 * * 1" ← 매주 월요일 오전 9시 }, { "path": "/api/cron/daily-sync", "schedule": "0 0 * * *" ← 매일 자정 } ] } // Cron 표현식: 분 시 일 월 요일 // * = 모두, 0 9 * * 1 = 매주 월(1) 9시 0분
대안: Supabase의 pg_cron 확장으로 DB 내부에서 직접 스케줄 실행 가능합니다. SQL로 정의하므로 별도 서버 불필요.

Webhook — 외부 서비스가 내 앱에 알림 보내기

반대 방향 통신입니다. 보통 내가 외부에 요청하지만, Webhook은 외부 서비스가 이벤트 발생 시 내 앱에 알려줍니다. Stripe 결제 완료·GitHub PR 생성 등.

Stripe 결제 Webhook 처리
// app/api/webhooks/stripe/route.ts export async function POST(req) { const sig = req.headers.get('stripe-signature') const body = await req.text() // 1. 서명 검증 (위조 차단) const event = stripe.webhooks.constructEvent( body, sig, process.env.WEBHOOK_SECRET ) // 2. 이벤트 종류별 처리 if (event.type === 'checkout.session.completed') { await grantAccess(event.data.object.customer_email) } return Response.json({ received: true }) }
핵심 보안: 누구나 webhook URL을 알면 가짜 요청을 보낼 수 있습니다. 서명 검증(signature verification)은 필수. 외부 서비스가 발행한 secret으로 본문을 해시해서 비교합니다.

Redis 캐싱 — 반복 조회를 메모리에서

DB는 디스크에서 읽으므로 느립니다. 자주 조회되는 데이터는 메모리(Redis)에 저장하면 100배 빨라집니다.

Upstash Redis 캐시 패턴
async function getUserStats(userId) { const cacheKey = `stats:${userId}` // 1. 캐시 먼저 확인 (1ms) const cached = await redis.get(cacheKey) if (cached) return cached // 2. 없으면 DB 조회 (100ms) const stats = await db.calculateStats(userId) // 3. 캐시에 저장 (5분 유효) await redis.set(cacheKey, stats, { ex: 300 }) return stats }
용도예시
세션 저장로그인 상태, JWT refresh token
Rate limiting1분당 요청 수 카운팅
실시간 카운터좋아요·조회수 (DB 부담 ↓)
큐 (Queue)이메일 발송·이미지 처리 대기열

tRPC — 타입 안전 API

REST API는 프론트·백엔드가 분리되어 타입이 안 맞으면 런타임 에러가 납니다. tRPC는 백엔드 함수를 프론트에서 그냥 함수처럼 호출하면서 타입까지 공유합니다.

REST API
fetch('/api/user').then(r => r.json())
응답 타입 직접 정의 필요
API 변경 시 양쪽 따로 수정
tRPC
trpc.user.get.useQuery()
타입 자동 추론
API 변경 시 컴파일 에러로 즉시 감지
적합한 경우: Next.js 같은 풀스택 TypeScript 프로젝트. 단일 팀이 프론트·백엔드 둘 다 관리할 때 강력합니다. 다른 언어 백엔드나 외부 클라이언트(모바일 앱) 대상이면 REST가 적합합니다.
Section 03 / 08
SECTION 04
Layer 4 · 데이터베이스

데이터를 저장하는 법

엑셀과 비슷한 구조, SQL로 명령합니다.

테이블
엑셀의 시트. 하나의 주제를 담은 집합.
행 (Row)
하나의 데이터. 항목 1건 = 1행.
열 (Column)
항목의 종류. 날짜, 부서, 유형 등.
Supabase 조회
supabase.from('reports') .select('*') .eq('dept', '서울팀') .order('date', { ascending: false })
참고: Supabase 대시보드에서 클릭만으로 조회 가능합니다.

SQL (관계형 DB)
표 구조. 데이터 간 관계 표현. Supabase, MySQL.
복잡한 집계·조인에 강함.
NoSQL (비관계형 DB)
문서·키값 구조. Firebase, MongoDB.
빠른 읽기, 유연한 구조에 강함.

SQL — 데이터베이스에 명령하는 언어

Structured Query Language. 거의 모든 관계형 DB에서 통하는 표준 언어. 4가지 명령만 알면 시작 가능합니다.

SQL 4대 명령
-- 1. 조회 (Read) SELECT name, email FROM users WHERE dept = '서울'; -- 2. 추가 (Create) INSERT INTO users (name, email) VALUES ('김민수', 'kim@example.com'); -- 3. 수정 (Update) UPDATE users SET dept = '부산' WHERE id = 5; -- 4. 삭제 (Delete) DELETE FROM users WHERE id = 5;
CRUD라고 부릅니다: Create(추가) + Read(조회) + Update(수정) + Delete(삭제). 데이터를 다루는 모든 작업의 기본입니다.

데이터 타입 — 컬럼의 종류

타입예시용도
text"안녕하세요"이름·이메일·내용
integer42정수·개수
numeric1234.56금액·소수
booleantrue / false참/거짓 (활성 여부 등)
timestamptz2026-05-21 14:30:00날짜+시간 (타임존)
uuida3f5...고유 식별자
jsonb{"key":"value"}JSON 데이터
Layer 4 · 데이터베이스 · 심화

키·관계와 보안

Primary Key, Foreign Key로 관계를 정의하고 RLS로 행 단위 보안을 만듭니다.

Primary Key (PK) · Foreign Key (FK)

테이블 간 관계의 핵심입니다. 엑셀로는 표현할 수 없는 데이터베이스만의 강점입니다.

Primary Key (PK)
고유 식별자
테이블 안에서 행을 구분하는 유일한 값.
보통 id 컬럼. 중복 불가.
Foreign Key (FK)
다른 테이블 참조
다른 테이블의 PK를 가리키는 값.
관계를 만들어주는 연결고리.
PK와 FK 예시
-- users 테이블 ┌────┬──────────┐ │ idname │ ← id가 PK ├────┼──────────┤ │ 1 │ 김민수 │ │ 2 │ 김영희 │ └────┴──────────┘ -- reports 테이블 ┌────┬────────────┬──────────┐ │ iddateuser_id │ ← user_id가 FK ├────┼────────────┼──────────┤ (users.id 참조) │ 1 │ 2026-01-05 │ 1 │ ← 김민수 보고서 │ 2 │ 2026-01-12 │ 2 │ ← 김영희 보고서 └────┴────────────┴──────────┘
왜 중요한가: FK 덕분에 reports에 이름을 직접 적지 않습니다. 김민수이 개명해도 users 테이블만 수정하면 모든 보고서에 자동 반영됩니다. 데이터 일관성의 핵심.

RLS (Row Level Security) — 행 단위 보안

RLS 정책
-- 자기 부서 데이터만 조회 가능 CREATE POLICY "dept_access" ON reports FOR SELECT USING ( dept = (SELECT dept FROM users WHERE id = auth.uid()) ); ALTER TABLE reports ENABLE ROW LEVEL SECURITY;
테이블 관계 + JOIN
-- reports → users 참조 ALTER TABLE reports ADD COLUMN user_id UUID REFERENCES users(id); // Supabase JOIN 조회 supabase.from('reports') .select('*, users(name, dept)')
RLS가 중요한 이유: API 코드를 잘 짜도 DB에 직접 접근하면 모든 데이터가 노출됩니다. RLS는 DB 자체에서 행 단위로 막는 마지막 보안선입니다.

웹 보안 — 알아야 할 3대 공격

DB 보안만으로 끝이 아닙니다. 웹앱의 일반적인 공격 3종은 반드시 방어해야 합니다.

공격방식방어
SQL Injection입력창에 SQL 코드 넣어 DB 직접 조작Prepared Statement, ORM 사용 (Supabase 자동 처리)
XSS댓글에 <script> 넣어 다른 사용자 PC에서 실행React는 기본 방어. dangerouslySetInnerHTML 만 조심
CSRF피해자가 로그인된 상태에서 악성 사이트가 요청 위조SameSite Cookie + CSRF Token. Next.js Server Action 자동 처리

Rate Limiting — 무차별 공격 차단

한 IP에서 1초에 1000번 요청 보내는 봇·공격자를 차단합니다.

Upstash Rate Limit 예시
import { Ratelimit } from '@upstash/ratelimit' const ratelimit = new Ratelimit({ limiter: Ratelimit.slidingWindow(10, '10 s') // 10초당 10회만 허용 }) const { success } = await ratelimit.limit(ip) if (!success) return Response.json( { error: '요청 너무 많음' }, { status: 429 })

HTTPS / SSL — 통신 암호화

좋은 소식: Vercel·Cloudflare·Netlify 등 모던 호스팅은 자동으로 HTTPS 인증서를 발급·갱신합니다(Let's Encrypt 기반, 무료). 도메인만 연결하면 끝. 별도 설정 불필요.

비밀번호 저장 — 절대 평문 금지

❌ 평문 저장
DB에 비밀번호 그대로 저장. 해킹 시 모든 사용자 비번 노출.
✅ 해시 저장 (bcrypt)
단방향 암호화. DB가 털려도 비밀번호 복구 불가. Supabase Auth는 자동 처리.

인덱스 — 데이터 많아져도 빠르게

책의 목차와 같습니다. 인덱스 없이 특정 행을 찾으려면 DB가 전체를 다 뒤져야 합니다. 1만 건은 괜찮지만 100만 건에서는 치명적입니다.

인덱스 생성
-- 자주 필터링하는 컬럼에 인덱스 CREATE INDEX idx_reports_dept ON reports(dept); CREATE INDEX idx_reports_date ON reports(created_at); -- 복합 인덱스 (dept + date 함께 조회 시) CREATE INDEX idx_reports_dept_date ON reports(dept, created_at); -- 인덱스 성능 확인 EXPLAIN ANALYZE SELECT * FROM reports WHERE dept = '서울';
인덱스 걸면 좋은 컬럼인덱스 안 걸어도 되는 경우
WHERE 절에 자주 쓰는 컬럼 (dept, status 등)데이터가 1만 건 미만
JOIN에 쓰는 FK 컬럼 (user_id, store_id)INSERT/UPDATE가 SELECT보다 훨씬 많은 경우
ORDER BY에 쓰는 컬럼 (created_at)이미 PK인 컬럼

트랜잭션 — 여러 작업을 하나로 묶기

주문 시 재고 차감과 결제 기록을 동시에 해야 한다면? 재고는 줄었는데 결제 기록이 실패하면 데이터가 꼬입니다. 트랜잭션은 "모두 성공 or 모두 취소"를 보장합니다.

트랜잭션 패턴
-- SQL 트랜잭션 BEGIN; UPDATE inventory SET stock = stock - 1 WHERE id = 1; INSERT INTO orders (user_id, item_id) VALUES (1, 1); COMMIT; ← 둘 다 성공해야 확정 ROLLBACK; ← 하나라도 실패하면 원래대로 // Supabase에서 RPC로 트랜잭션 실행 await supabase.rpc('process_order', { p_user_id: userId, p_item_id: itemId })
Supabase에서 트랜잭션: JS에서 직접 트랜잭션을 제어하기 어려우므로, DB 함수(PostgreSQL Function)를 만들고 supabase.rpc()로 호출하는 게 표준입니다.

N+1 쿼리 — 흔한 성능 함정

리스트 조회 후 각 항목마다 추가 쿼리를 날리는 패턴. 100개 게시물을 보여주면 DB 요청이 101번 발생합니다.

❌ N+1 (느림)
SELECT * FROM reports
→ 100건 가져옴
→ 각 건마다 SELECT name FROM users WHERE id=?
→ DB 요청 101번
✅ JOIN (빠름)
SELECT reports.*, users.name FROM reports JOIN users ON ...
→ DB 요청 1번으로 해결
Supabase N+1 해결 — 중첩 select
// ❌ N+1 유발 const reports = await supabase.from('reports').select('*') for (const r of reports.data) { r.user = await supabase.from('users').select().eq('id', r.user_id) } // ✅ 중첩 select로 한 번에 const reports = await supabase .from('reports') .select('*, users(name, email)') ← 1번 쿼리로 해결

집계 함수 — 통계·리포트의 기본

데이터를 합치고 요약합니다. 대시보드·KPI·리포트는 모두 집계 함수 위에 만들어집니다.

5대 집계 함수
-- 1. COUNT — 행 개수 SELECT COUNT(*) FROM reports; -- 전체 보고서 수 -- 2. SUM — 합계 SELECT SUM(amount) FROM payments; -- 총 매출 -- 3. AVG — 평균 SELECT AVG(rating) FROM reviews; -- 평균 평점 -- 4. MIN / MAX — 최소·최대 SELECT MIN(price), MAX(price) FROM products; -- 5. GROUP BY — 카테고리별 집계 (가장 강력) SELECT dept, COUNT(*) FROM reports GROUP BY dept; -- 서울 → 42건, 부산 → 18건, 대전 → 9건
HAVING vs WHERE: WHERE는 그룹화 전 필터, HAVING은 그룹화 후 필터. HAVING COUNT(*) > 10 → 10건 이상인 부서만.

마이그레이션 — 스키마 변경 이력 관리

테이블·컬럼을 추가·변경할 때마다 코드처럼 파일로 기록합니다. 개발·스테이징·운영 환경에 동일하게 적용되며, 팀원들도 같은 DB 구조로 작업 가능합니다.

Supabase 마이그레이션 흐름
# 1. 새 마이그레이션 파일 생성 supabase migration new add_severity_column # 2. supabase/migrations/20260520_add_severity_column.sql 자동 생성 ALTER TABLE reports ADD COLUMN severity text DEFAULT 'minor'; # 3. 로컬 DB에 적용 & 테스트 supabase db reset # 4. 운영 DB에 push supabase db push
도구특징
Supabase CLISupabase 전용, SQL 파일 직접 작성
Prisma Migrateschema.prisma 변경 → SQL 자동 생성
Drizzle KitTypeScript 스키마 정의, 가벼움
주의 — 운영 DB에서 절대 직접 ALTER 금지: 마이그레이션 파일을 거치지 않으면 팀원·다른 환경과 어긋나서 추적 불가능한 버그가 생깁니다.
Section 04 / 08
SECTION 05
Layer 5 · 인프라

서버·배포· 환경변수

코드를 인터넷에 올리는 전 과정입니다. 언어와 스택에 따라 호스팅 서비스가 달라집니다.

로컬
내 PC
개발 환경. 나만 접속.
localhost:3000
Vercel
Next.js 최적화
git push → 자동 배포.
JS/TS 앱에 최적.
PythonAnywhere
Python 전용
Flask·Django 앱 전용.
무료 플랜 제공.

호스팅 서비스 비교 — 어떤 걸 언제 쓰나

서비스언어/스택배포무료적합한 경우
VercelJS / TypeScriptgit push 자동비상업용Next.js 앱, 빠른 출시
PythonAnywherePythongit pull 수동✅ 상시 무료Flask·Django, 소형 내부 도구
Railway무관 (Docker)git push 자동$5 크레딧풀스택, DB 포함 한 플랫폼
AWS AmplifyJS / Pythongit push 자동12개월 무료AWS 연동 필수, 기업 환경
GitHub PagesHTML/CSS/JSgit push 자동✅ 상시 무료정적 사이트, 포트폴리오
NetlifyJS / TypeScriptgit push 자동상업용 가능Vercel 대안, 팀 무제한 시트
배포 흐름 비교
// Vercel (Next.js) 코드 수정 git push 자동 빌드 전 세계 배포 // PythonAnywhere (Flask) 코드 수정 SSH 접속 git pull 서버 재시작

CDN — 사용자 근처에 미리 갖다놓기

Content Delivery Network. 전 세계 곳곳에 서버 복사본을 둬서, 사용자와 가장 가까운 곳에서 파일을 전달하는 구조입니다.

CDN 없음
사용자(서울) → 서버(미국)
왕복 200ms · 느림 · 트래픽 폭주 시 다운
CDN 사용
사용자(서울) → CDN(서울/도쿄) → 원본
20ms · 빠름 · DDoS 방어
Vercel은 CDN 내장: Next.js 배포 시 자동으로 전 세계 Edge에 분산됩니다. 별도 설정 불필요.

Cloudflare — 추가 보안·속도 레이어

Vercel 앞단에 무료로 끼워넣을 수 있는 보안·CDN 서비스. DDoS 공격 트래픽 과금을 막아주는 효과가 큽니다.

제공FreePro
대역폭무제한무제한
DDoS 방어
글로벌 Edge330+ 도시330+ 도시
SSL 인증서
가격$0$20/월
왜 무료 플랜으로 충분한가: Vercel 단독 사용 시 DDoS 공격 트래픽도 $0.15/GB 과금됩니다 (실제 $23,000 청구 사례 존재). Cloudflare를 앞에 두면 공격이 Vercel에 도달하기 전에 차단됩니다.

호스팅 서비스 전체 지도

목적별로 사용하는 서비스가 다릅니다. 카테고리로 묶어서 이해해야 합니다.

카테고리서비스역할대안
프론트엔드 배포VercelNext.js 앱 호스팅Netlify, Cloudflare Pages
백엔드 + DBSupabasePostgreSQL + 인증 + 스토리지Firebase, Appwrite, PocketBase
풀스택 통합Railway프론트+백+DB 한 곳Render, Fly.io
CDN + 보안Cloudflare속도 + DDoS 방어Bunny.net, AWS CloudFront
엔터프라이즈AWSAmplify + Cognito + RDS + S3NCP (국내 IDC)
일반 조합: Vercel + Supabase가 가장 빠른 출시. 트래픽이 커질수록 Cloudflare(무료) 추가로 DDoS 방어 + 비용 절감. 사내 보안 정책 따라 AWS·NCP 전환도 가능합니다.

Git과 GitHub — 코드의 시간여행

개발자가 매일 쓰는 도구. 코드 변경 기록을 저장하고 되돌릴 수 있게 해줍니다.

Git
버전 관리 도구
내 컴퓨터에서 동작. 코드 변경 기록(스냅샷) 저장.
GitHub
클라우드 저장소
Git 기록을 인터넷에 백업. 협업 + 자동 배포 연동.
Git 기본 명령어
git add . # 변경한 파일 선택 git commit -m "메시지" # 변경 기록 저장 (스냅샷) git push # GitHub에 업로드 git pull # GitHub에서 최신 코드 받기
왜 중요한가: 코드를 망쳐도 이전 시점으로 되돌릴 수 있습니다. 여러 명이 동시에 작업해도 충돌이 정리됩니다. 그리고 Vercel은 GitHub push를 감지해서 자동 배포합니다.

npm — 남이 만든 코드 가져다 쓰기

모든 기능을 처음부터 만들 필요가 없습니다. 전 세계 개발자가 만든 200만+ 패키지를 무료로 가져다 쓸 수 있습니다.

패키지 설치 흐름
npm install react # React 라이브러리 설치 npm install lucide-react # 아이콘 라이브러리 설치 # package.json에 자동 기록 { "dependencies": { "react": "^19.0.0", "lucide-react": "^0.383.0" } }
이게 모던 웹 개발의 본질: Next.js, Supabase, Tailwind — 모두 npm으로 설치합니다. .env.local.gitignore에 들어가는 이유도 같은 맥락. 비밀번호는 절대 공개 저장소에 올라가면 안 됩니다.

환경변수 없이 (❌)
API 키를 코드에 직접 작성 → GitHub에 올라가면 보안 위험. 절대 금지.
환경변수 사용 (✅)
.env.local에 저장. 코드에는 process.env.KEY로 참조. 안전하게 관리.

PWA — 웹앱을 모바일 앱처럼

Progressive Web App. 일반 웹사이트에 두 가지 파일만 추가하면 앱스토어 없이 스마트폰 홈화면에 설치되고, 오프라인에서도 작동하는 앱이 됩니다.

일반 웹사이트
브라우저 열어야 접속 가능
인터넷 끊기면 작동 안 됨
알림 못 보냄
PWA
홈화면 아이콘으로 실행
오프라인 작동 (캐시된 데이터)
푸시 알림 가능

필요한 2가지 파일

파일역할
manifest.json앱 이름·아이콘·테마색 등 메타 정보. 홈화면에 추가될 때 사용됨.
service-worker.js백그라운드 스크립트. 오프라인 캐시·푸시 알림 담당.
manifest.json 예시
{ "name": "내 업무 앱", "short_name": "업무앱", "start_url": "/", "display": "standalone", ← 브라우저 UI 숨김 "background_color": "#ffffff", "theme_color": "#2563eb", "icons": [ { "src": "/icon-192.png", "sizes": "192x192" }, { "src": "/icon-512.png", "sizes": "512x512" } ] }

왜 PWA를 쓰나 — 네이티브 앱 vs PWA

항목네이티브 앱 (iOS·Android)PWA
개발iOS(Swift)·Android(Kotlin) 별도웹 코드 그대로 사용
배포앱스토어 심사 (1~2주)URL 공유 즉시
업데이트사용자가 직접 업데이트자동 (캐시 갱신)
설치앱스토어에서 다운로드브라우저에서 "홈 화면에 추가"
비용Apple $99/년, Google $25 (1회)무료
기능 제약모든 하드웨어 접근일부 제한 (iOS 푸시 등)
PWA가 적합한 경우: 사내 도구, B2B 서비스, 매장·현장에서 쓰는 모바일 앱. 앱스토어 등록 부담 없이 URL 공유로 즉시 배포 가능. Next.js는 next-pwa 패키지로 쉽게 추가됩니다.

앱스토어 출시가 목표라면 — React Native·Expo vs Flutter

PWA로 커버 안 되는 기능(카메라·블루투스·위젯 등)이 필요하거나 앱스토어에 정식 출시해야 한다면 네이티브 앱을 선택합니다.

기술언어추천 상황Claude Code 지원
React Native + ExpoJavaScript·TypeScript이미 React를 배웠거나 빠른 출시가 목표. 바이브코딩에 최적. 커뮤니티 방대✅ 강력 (Expo Skills 존재)
FlutterDartiOS·Android 픽셀 완벽 일치가 필요할 때. UI 자유도 높음. 별도 언어 학습 필요🟡 가능
PWAJavaScript·TypeScript사내 도구·B2B. 앱스토어 불필요. 가장 빠름✅ Next.js 그대로
바이브코더에게 추천 경로: 웹 먼저 → PWA로 모바일 지원 → 앱스토어 출시가 필요하면 React Native·Expo로 확장. Expo는 동일한 React 문법을 쓰므로 학습 비용이 가장 낮습니다.
Layer 5 · 인프라 · 심화

CI/CD와 스택 선택

환경 분리, 자동화, 그리고 언어별 스택 선택 기준입니다.

스택 비교 — Flask vs Next.js

항목Flask + PythonAnywhereNext.js + Vercel
언어PythonTypeScript
렌더링서버사이드 (Jinja2 템플릿)SSR / CSR / SSG 혼합
실시간 UI제한적 (페이지 새로고침)✅ React 상태 기반
배포 자동화수동 (git pull + 재시작)✅ git push 자동 배포
데이터 처리✅ pandas, numpy 등 강력JS 라이브러리 사용
진입 장벽낮음 (Python 친숙)중간 (TypeScript 필요)

환경 분리 (Next.js 기준)

1
개발 (Local).env.local — 개발용 Supabase, 테스트 데이터
2
스테이징 (Vercel Preview)PR 올리면 자동 생성. 배포 전 QA 환경.
3
프로덕션 (Vercel Production)main 브랜치 머지 시 자동 배포.
환경별 변수 분리
SUPABASE_URL = https://prod.supabase.co # Production SUPABASE_URL = https://dev.supabase.co # Preview
언제 Flask를 쓰나? 데이터 분석(pandas), AI/ML(scikit-learn)처럼 Python 생태계가 필요할 때. UI 복잡도가 낮고 빠르게 만들어야 할 때 유리합니다. UI가 복잡해질수록 React 기반이 더 적합합니다.

환경변수 보안 — 절대 코드에 비밀번호를 쓰지 마라

API 키, DB 비밀번호, 인증 토큰은 코드에 직접 쓰면 안 됩니다. .env.local 파일에 분리하고, 이 파일은 git에 올라가지 않게 막아야 합니다.

.gitignore — git 추적 제외 파일 목록
node_modules/ # 설치한 패키지 (용량 큼) .env.local # 비밀 환경변수 ★ .env.production # 프로덕션 환경변수 ★ .next/ # Next.js 빌드 결과물 *.log # 로그 파일
실수로 올렸다면? 키를 즉시 폐기(rotate)하고 새로 발급해야 합니다. git 기록을 지워도 GitHub는 이미 봇이 키를 수집한 뒤일 수 있습니다. 매년 수많은 회사가 이 실수로 해킹당합니다.
3가지 키 종류:
Public key (NEXT_PUBLIC_*) — 브라우저에 노출 OK. 예: Supabase ANON_KEY
Secret key — 서버에서만 사용. 예: SERVICE_ROLE_KEY
Webhook secret — 외부 서비스가 신호 보낼 때 검증용

모니터링·로깅 — 배포 후 무엇이 일어나는지 추적

배포가 끝이 아닙니다. 실제 사용자가 어디서 막히는지·어떤 에러가 나는지 모르면 개선 불가능합니다.

도구역할비용
Sentry에러 자동 수집·알림무료 (월 5k 이벤트)
Vercel Analytics페이지뷰·핵심 지표(Web Vitals)무료 (Hobby 제한)
PostHog사용자 행동 추적·세션 녹화무료 (월 100만 이벤트)
LogTail / Axiom서버 로그 검색·분석무료 티어
최소 셋업: Sentry + Vercel Analytics 2개만으로도 핵심 에러·성능 문제는 대부분 잡힙니다. 4줄 코드 추가로 끝.

결제 시스템 — 유료 서비스 만들 때

직접 결제 처리는 PCI DSS 등 보안 인증이 필요해 사실상 불가능합니다. SaaS 결제 서비스를 거쳐야 합니다.

서비스대상수수료특징
Stripe글로벌2.9% + 30¢업계 표준. 구독·일회성·인보이스 다 지원.
Lemon Squeezy디지털 상품5%세금 처리 자동 (Merchant of Record).
Toss Payments국내~3.3%한국 카드 모두 지원. 간편결제 강함.
Paddle글로벌 SaaS5% + 50¢VAT·sales tax 자동 처리.
Merchant of Record가 중요한 이유: Lemon Squeezy·Paddle은 "판매자"로 등록되어 전 세계 세금을 대신 처리합니다. Stripe는 결제 처리만 하므로 세금 신고는 직접 해야 합니다. 글로벌 B2C라면 MoR 서비스가 압도적으로 편리합니다.

도메인·DNS — 내 서비스에 주소 붙이기

myapp.vercel.app 같은 임시 주소가 아닌 myapp.com 같은 정식 도메인을 연결하는 과정입니다.

1
도메인 구입Gabia·Cafe24·Namecheap·Cloudflare Registrar (연 $10~15)
2
호스팅에 도메인 등록Vercel 대시보드 → Settings → Domains → 도메인 입력
3
DNS 레코드 설정도메인 구입처에서 Vercel이 알려준 값 입력
4
SSL 자동 발급Vercel이 Let's Encrypt로 자동 처리 (1~5분)

DNS 레코드 종류

종류역할예시 값
A도메인 → IPv4 주소76.76.21.21
AAAA도메인 → IPv6 주소2606:4700:...
CNAME도메인 → 다른 도메인 별칭cname.vercel-dns.com
MX이메일 서버 지정aspmx.l.google.com
TXT인증·검증용 텍스트v=spf1 include:_spf...
가장 흔한 설정: 루트 도메인(myapp.com)은 A 레코드, www.myapp.com은 CNAME. 둘 다 Vercel이 알려주는 값 그대로 입력하면 됩니다. 변경 후 적용까지 5분~48시간 (DNS propagation).

Docker — "내 컴퓨터에선 됐는데" 문제 해결

코드·종속성·OS 설정을 통째로 컨테이너에 담아 어디서든 동일하게 실행되게 합니다.

Docker 없을 때
로컬: Node 20, macOS
서버: Node 18, Ubuntu
→ 같은 코드가 다르게 동작
Docker 사용
컨테이너 내부: Node 20, Linux
→ 로컬·서버 모두 동일 환경
→ "내 컴에선 됐는데" 사라짐
Dockerfile 예시 (Next.js)
FROM node:20-alpine # 베이스 이미지 WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build EXPOSE 3000 CMD ["npm", "start"]
Vercel·Netlify는 Docker 불필요: 빌드 환경이 표준화되어 있어 Dockerfile 없이 그냥 git push만 하면 됩니다. AWS·자체 서버에 배포할 때만 Docker가 필수가 됩니다.
Section 05 / 08
SECTION 06
실전 연결

웹앱 실제 흐름

사용자가 데이터를 조회하고 저장하는 전 과정입니다.

1
URL 접속브라우저 → HTTP 요청
2
라우팅App Router → page.tsx 실행
3
DB 조회서버 → Supabase 쿼리
4
데이터 수신Skeleton → 실제 데이터 fade-in
5
화면 구성React 컴포넌트 조립 → 출력
6
인터랙션클릭 → State → 자동 업데이트
7
저장 요청POST API 호출 → 검증
8
완료DB 저장 → 성공 → 화면 업데이트

바이브코딩 시작 — PRD부터 작성

코딩 전에 "무엇을 만들지" 먼저 정리해야 합니다. PRD(Product Requirements Document)는 AI에게 컨텍스트를 한 번에 전달하는 가장 좋은 방법입니다.

PRD.md — AI에게 전달할 요구사항 문서
# 사고 보고 시스템 ## 1. 만들려는 것 (한 줄) 부서별로 사고를 기록·조회하고 월간 통계를 보여주는 사내 대시보드 ## 2. 타겟 사용자 - 일반 직원: 사고 기록 작성 - 부서장: 부서 사고 조회·통계 확인 - 안전관리자: 전 부서 통합 통계 ## 3. 핵심 기능 (MVP — 최소 기능) 1. 사고 등록 폼 (날짜·부서·유형·내용) 2. 사고 목록 조회 (부서별 필터) 3. 월별 통계 차트 ## 4. 나중에 추가할 기능 (V2) - 사진 첨부, PDF 출력, 카카오톡 알림 ## 5. 기술 스택 Next.js 15 + Supabase + Tailwind + shadcn/ui ## 6. 디자인 원칙 - 한 화면에 핵심 정보 다 보이기 - 모바일 우선 (현장에서 사용)
핵심 규칙: AI에게 "사고 보고 시스템 만들어줘" 보다 위 PRD를 통째로 주면 결과 품질이 5배 차이납니다. 만들기 전에 5분 정리하는 게 5시간 디버깅을 막습니다.

이터레이션 루프 — 한 번에 완성하려 하지 말 것

바이브코딩은 "한 번에 완벽"이 아니라 "작게 만들고 반복"입니다. 아래 5단계 루프를 지킬수록 결과가 좋아집니다.

1
설명"이 기능을 만들어줘" — PRD에서 한 조각만 떼서 명확히
2
생성AI가 코드 작성. 한 파일·한 기능 단위로 제한
3
실행·확인npm run dev로 실제 동작 확인. 화면·기능 직접 테스트
4
피드백안 되면 에러 그대로 전달 / 잘 되면 다음 조각 진행
5
커밋잘 작동하는 시점에 git commit — 다음 단계 실패해도 안전
실패 패턴: "한 번에 다 만들어줘" → AI가 거대한 코드 생성 → 어디가 문제인지 모름 → 처음부터 다시. 작게 만들고 자주 커밋이 핵심입니다.

Git 안전망 — 실험할 수 있는 용기

바이브코딩의 두려움 중 하나는 "AI가 뭔가 망치면 어쩌지?" 입니다. Git이 그 두려움을 없애줍니다.

상황명령어효과
작동하는 시점 저장git add . && git commit -m "메시지"이 시점으로 언제든 돌아올 수 있음
실험 시작git checkout -b 실험브랜치메인 코드 안 건드리고 별도 공간에서 시도
망쳤을 때 되돌리기git checkout .커밋 후 변경 사항 전부 취소
특정 파일만 되돌리기git checkout 파일경로해당 파일만 마지막 커밋 상태로
실험 성공 → 합치기git checkout main && git merge 실험브랜치메인 코드에 변경사항 적용
바이브코딩 황금률: "잘 되는 시점이 보이면 즉시 커밋." AI에게 새 작업 지시 전에 커밋해두면, 망쳐도 1초 만에 복구됩니다.

Git 충돌(Merge Conflict) 해결법 — 가장 많이 막히는 순간

브랜치를 합칠 때 같은 파일을 양쪽이 다르게 수정했으면 Git이 결정을 못하고 사람에게 맡깁니다. 터미널에 나타나는 표시만 이해하면 충분합니다.

충돌 났을 때 파일 안에 나타나는 표시
<<<<<<< HEAD ← 내 브랜치 코드 const title = '사고 보고서' ======= ← 경계선 const title = '안전 사고 보고서' >>>>>>> feature/update-title ← 합치려는 브랜치 코드
단계할 일명령어 / 방법
1충돌 파일 목록 확인git status → "both modified" 파일 목록 확인
2충돌 표시 제거 · 원하는 코드 선택파일 열어서 <<< === >>> 3줄 삭제, 남길 코드만 유지
3해결 완료 후 커밋git add .git commit -m "충돌 해결"
AI에게 충돌 맡기기: 충돌 파일 전체를 복사 → AI에게 "이 파일에 Git 충돌이 발생했어. <<<<<<< ======= >>>>>>> 표시를 제거하고 두 변경사항을 합쳐줘. 최신 기능 기준으로"라고 하면 됩니다.
충돌 예방: 같은 파일을 여러 브랜치에서 동시에 수정하지 않기. 자주 git pull해서 최신 상태 유지하기.
실전 연결 · 심화

인증 흐름과 3상태 패턴

로그인부터 권한 분기, 상태 처리까지입니다.

인증 흐름 (Supabase Auth)

1
로그인사번+비밀번호 → supabase.auth.signIn()
2
세션 생성JWT 토큰 발급 → 쿠키 저장
3
미들웨어모든 요청 시 middleware.ts에서 토큰 확인
4
권한 분기role에 따라 다른 화면 표시

JWT · 쿠키 · localStorage — 어떻게 다른가

방식저장 위치특징
JWT토큰 자체에 정보 담음서버가 매번 DB 조회 불필요. 빠름.
쿠키 (HttpOnly)브라우저JS 접근 불가 → XSS 공격 방어. 자동 전송.
localStorage브라우저JS 접근 가능 → XSS 위험. 토큰 저장에 비추천.
JWT 토큰 구조
// 점(.) 3개로 구분된 문자열 eyJhbGc... . eyJzdWIi... . SflKxwRJ... 헤더 페이로드 서명 (알고리즘) (사용자 정보) (위변조 방지) // 디코딩하면: { "sub": "user-123", "role": "admin", "exp": 1735689600 }
핵심 원리: JWT는 서버가 발급할 때 "서명"을 붙입니다. 사용자가 위변조해도 서명이 안 맞으므로 서버가 거부합니다. 그래서 토큰만으로 인증이 가능합니다.

3가지 UI 상태 항상 처리

Loading
Skeleton UI. 기다리고 있음을 알림.
Error
인라인 에러 + 재시도 버튼. 토스트 금지.
Empty
데이터 없을 때 안내 문구.
왜 3가지 상태를 모두 처리해야 하나? 데이터가 오기 전(loading), 실패했을 때(error), 데이터가 없을 때(empty) — 이 세 상황을 처리 안 하면 사용자는 흰 화면만 봅니다.

소셜 로그인 — OAuth 흐름

Google·Kakao·GitHub 등 외부 서비스로 로그인하는 방식. "비밀번호 없이 Google로 로그인" 버튼이 이 방식입니다.

1
로그인 버튼 클릭앱이 Google/Kakao로 리다이렉트
2
외부 서비스 인증사용자가 Google에서 로그인 승인
3
인가 코드 발급Google이 앱으로 code 파라미터와 함께 리다이렉트
4
토큰 교환앱 서버가 code → Access Token으로 교환
5
로그인 완료사용자 정보(이름·이메일) 획득, 세션 생성
Supabase OAuth — 3줄로 구현
// Google 로그인 버튼 클릭 시 await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: 'https://myapp.com/auth/callback' } }) // Supabase가 OAuth 흐름 전부 처리 // 콜백 URL에서 세션 자동 저장
Supabase 지원 OAuth 제공자: Google, GitHub, Kakao, Apple, Twitter(X), Discord, Slack 등. Supabase 대시보드에서 Client ID·Secret만 입력하면 연동됩니다.

RBAC — 역할 기반 권한 관리

Role-Based Access Control. "관리자는 모두 볼 수 있고, 일반 직원은 자기 데이터만 본다"를 DB·미들웨어·UI 3곳에서 동시에 제어합니다.

역할 (Role)볼 수 있는 것할 수 있는 것
admin전체 데이터생성·수정·삭제·설정 변경
manager자기 팀 데이터생성·수정
member자기 데이터만생성만
viewer공개 데이터만조회만
RBAC 3계층 구현
// 1. DB — RLS로 행 단위 차단 CREATE POLICY "manager_access" ON reports FOR ALL USING ( auth.uid() IN ( SELECT id FROM users WHERE role IN ('admin', 'manager') ) ); // 2. 미들웨어 — 페이지 접근 차단 if (user.role !== 'admin') { return NextResponse.redirect('/unauthorized') } // 3. UI — 버튼·메뉴 숨기기 {user.role === 'admin' && <DeleteButton />}
3계층 모두 필요한 이유: UI만 숨기면 URL 직접 접속으로 뚫립니다. 미들웨어만 막으면 API 직접 호출로 뚫립니다. DB RLS는 최후의 방어선. 3계층이 모두 있어야 완전합니다.

SEO — 검색엔진 최적화

공개 서비스라면 구글 검색에 잘 노출되어야 합니다. Next.js는 SSR/SSG 덕분에 React SPA보다 SEO에 강합니다.

요소역할구현
메타 태그제목·설명·키워드Next.js metadata export
OG 이미지SNS 공유 시 카드 이미지openGraph.images 설정
sitemap.xml전체 페이지 목록app/sitemap.ts 자동 생성
robots.txt크롤러 허용 규칙app/robots.ts
구조화 데이터검색결과 풍부한 표시JSON-LD 스키마
Next.js 메타데이터
// app/page.tsx export const metadata = { title: 'My App — 업무 자동화 도구', description: '30초만에 시작하는...', openGraph: { title: 'My App', images: ['/og-image.png'], // 1200x630 권장 }, }

i18n — 다국어 처리

서비스를 글로벌하게 운영하려면 다국어 지원이 필요합니다. next-intl이 표준 라이브러리입니다.

next-intl 패턴
// messages/ko.json { "home": { "title": "환영합니다" } } // messages/en.json { "home": { "title": "Welcome" } } // 컴포넌트에서 사용 const t = useTranslations('home') <h1>{t('title')}</h1> // → URL이 /ko면 "환영합니다", /en이면 "Welcome"
URL 전략 3가지:
• 하위 경로: myapp.com/ko/about (가장 흔함)
• 서브도메인: ko.myapp.com
• 다른 도메인: myapp.co.kr / myapp.com
SEO 효과는 도메인 분리가 가장 강하지만 운영 복잡도 ↑

테스트 — 코드가 잘 작동하는지 자동 검증

수동 테스트는 빠뜨리는 게 생깁니다. 테스트 코드를 작성하면 코드 변경 시마다 자동으로 검증됩니다.

종류검사 대상도구
단위 테스트함수 1개 결과Vitest, Jest
컴포넌트 테스트React 컴포넌트 렌더Testing Library
E2E 테스트브라우저 자동화 (실제 유저 흐름)Playwright, Cypress
API 테스트API Route 응답 검증Vitest + supertest
Playwright E2E 테스트
import { test, expect } from '@playwright/test' test('로그인 후 대시보드 접근', async ({ page }) => { await page.goto('/login') await page.fill('#email', 'test@example.com') await page.fill('#password', '1234') await page.click('button[type=submit]') await expect(page).toHaveURL('/dashboard') await expect(page.locator('h1')).toHaveText('대시보드') })

멀티테넌시 — 여러 조직이 같은 앱을 쓰는 구조

SaaS의 핵심 구조. 한 시스템에 여러 회사·팀이 가입해서 각각 자기 데이터만 보는 방식입니다. Slack·Notion이 이렇게 동작합니다.

방식특징적합한 경우
단일 DB + tenant_id 컬럼모든 테이블에 tenant_id, RLS로 격리대부분의 SaaS. 비용 효율 최고
DB 분리고객사마다 별도 DB엔터프라이즈, 보안 요구 강함
스키마 분리같은 DB, 다른 스키마중간 규모 격리 필요
tenant_id + RLS 패턴
-- 모든 테이블에 tenant_id 컬럼 CREATE TABLE reports ( id uuid PRIMARY KEY, tenant_id uuid NOT NULL, ← 어떤 조직 소속인지 content text ); -- RLS로 자기 조직 데이터만 보이게 CREATE POLICY tenant_isolation ON reports FOR ALL USING ( tenant_id = (SELECT tenant_id FROM users WHERE id = auth.uid()) );
핵심 원칙: tenant_id를 어디서든 빠뜨리면 데이터 유출. RLS로 DB 자체에서 강제하는 게 안전합니다.
Section 06 / 08
SECTION 07
개념 총정리

웹 개발 전체 요약

이 가이드에서 배운 모든 개념을 한 눈에 정리합니다.

레이어 구조 — 역할 분담

레이어역할주요 기술한 줄 요약
프론트엔드화면HTML·CSS·React·Next.js·Tailwind·shadcn사용자가 보는 모든 것
백엔드로직Next.js API Route·Node.js데이터를 처리하는 두뇌
데이터베이스저장Supabase·PostgreSQL·SQL데이터를 영구적으로 보관
인프라배포·운영Vercel·Cloudflare·Git·Docker·PWA코드를 인터넷에 올려 유지
보안방어RLS·JWT·HTTPS·RBAC데이터와 사용자를 지키는 것
AI·Agent자동화Claude Code·Cursor·MCP·Skill개발 속도를 10배로 올리는 도구

핵심 도구 — 역할 한 줄 정리

🧱
HTML / CSS모든 화면의 뼈대와 스타일
JavaScript / TypeScript화면을 동적으로 제어하는 언어
⚛️
React컴포넌트 조립 + 상태 자동 반영
🔺
Next.jsReact + 서버 + 라우팅 올인원
🎨
Tailwind + shadcn/ui클래스 방식 스타일 + 부품 모음
🗄️
SupabasePostgreSQL + 인증 + 스토리지 + RLS
🚀
Vercelgit push 한 번으로 전 세계 배포
🔒
보안 (RLS·JWT·HTTPS)DB 행 단위 제어 + 암호화 통신
📱
PWA홈화면 설치형 모바일 앱 (앱스토어 불필요)
🔄
CI/CD + Git코드 변경 → 자동 배포 파이프라인
🤖
MCP + SkillAI가 외부 도구·전문지식 자동 활용
🧠
개념 이해 = AI 활용 수준Claude Code·Cursor 등 AI 코딩 도구는 개발자의 이해 수준만큼 좋은 결과를 냅니다. 이 가이드가 그 차이를 만듭니다.

데이터 흐름 — 사용자 요청부터 화면까지

1
URL 접속브라우저가 서버로 HTTP 요청 전송
2
라우팅Next.js App Router → 해당 page.tsx 실행
3
인증 확인미들웨어 → JWT 검증 → 권한 없으면 로그인 이동
4
DB 조회Server Component → Supabase → PostgreSQL (RLS 적용)
5
화면 구성React 컴포넌트 조립 → Skeleton → 실제 데이터 전환
6
인터랙션클릭 → State 변경 → 해당 컴포넌트 자동 업데이트
7
저장 완료POST API → 검증 → DB 저장 → 성공 토스트
개념 총정리 · 심화

심화 개념 전체 정리

기초·심화 과정에서 다룬 모든 개념을 영역별로 압축합니다.

프론트엔드

개념한 줄 정의왜 중요한가
Server / Client Component서버 실행(DB 접근) vs 브라우저 실행(상태·이벤트)성능·보안의 기본 분리
SSR / SSG / CSR / ISR언제·어디서 HTML을 생성하는가페이지 성격에 맞는 렌더링 선택
TypeScript타입 정의로 버그를 코드 작성 시점에 잡음any·as 남발 시 무용지물
Zustand / Context / URL State전역·컴포넌트·URL 상태 관리 3가지 방식용도에 맞는 선택이 핵심
TanStack Query서버 데이터 자동 캐싱·갱신단순 fetch의 로딩·캐시·에러 문제 해결
react-hook-form + zod폼 상태 + 타입 안전 검증프론트·백엔드 검증 일치
Error Boundary컴포넌트 에러를 격리해 흰 화면 방지Next.js error.tsx로 자동 처리
접근성 (a11y)색+텍스트+아이콘 3중 표기, 44px 터치 타겟색맹·키보드·스크린리더 사용자 포함
성능 최적화이미지·코드분할·폰트·캐싱·번들 최소화모바일 Lighthouse 90+ 달성

백엔드

개념한 줄 정의왜 중요한가
Middleware모든 요청을 가로채 인증·리다이렉트 처리페이지 단위 접근 제어의 2번째 방어선
JWT + HttpOnly Cookie서명된 토큰으로 인증 상태 유지localStorage 저장은 XSS에 취약
OAuth (소셜 로그인)Google·Kakao 등 외부 서비스로 인증 위임5단계 흐름, Supabase 3줄로 구현
WebSocket / SSE / Realtime서버가 먼저 브라우저에 데이터를 보내는 방식Supabase Realtime이 DB 변경을 즉시 반영
Webhook외부 서비스(Stripe·GitHub)가 내 서버에 이벤트 알림서명 검증 필수, passive true로 처리
Redis 캐싱반복 DB 조회를 메모리에서 처리 (100배 빠름)Rate Limiting·세션·큐에도 활용
Cron Job정해진 시간에 자동 실행 (일일 집계·주간 리포트)Vercel cron.json 또는 pg_cron으로 구현
파일 업로드 / Presigned URL서버 부하 없이 S3·Supabase Storage 직접 업로드1회용 URL → 완료 후 DB에 경로 저장
RAG + LLM API내 문서 검색 → 컨텍스트 + 질문을 AI에 전달사내 정보로 AI 챗봇 구현의 표준 패턴
tRPCTypeScript 타입을 프론트·백엔드가 공유하는 API 레이어API 변경 시 컴파일 에러로 즉시 감지

데이터베이스

개념한 줄 정의왜 중요한가
PK / FK행을 고유 식별 / 테이블 간 관계 연결데이터 무결성의 기반
RLSDB 행 단위 접근 제어 정책API 우회해도 데이터 보호 — 최후 방어선
Index자주 조회하는 컬럼에 목차 생성100만 건에서 1ms vs 1000ms 차이
Transaction여러 작업을 원자적 단위로 묶기부분 실패 시 전체 취소 — 데이터 일관성
N+1 쿼리반복 조회로 DB 요청 폭증Supabase 중첩 select로 1번에 해결
집계 함수COUNT·SUM·AVG·GROUP BY대시보드·KPI·리포트의 모든 통계
Migration스키마 변경을 파일로 기록·관리팀 협업·운영 배포의 기본
Vector DB텍스트 임베딩을 저장·검색RAG의 핵심 인프라 (Supabase pgvector)

보안

공격/개념내용방어
XSS입력에 스크립트 삽입 → 타 사용자 브라우저 실행React 기본 방어 / dangerouslySetInnerHTML 주의
CSRF로그인 상태에서 악성 요청 위조SameSite Cookie / Next.js Server Actions 자동 처리
SQL Injection입력에 SQL 삽입 → DB 직접 조작Supabase SDK·Prisma 사용 시 자동 방어
RBAC역할 기반 접근 제어DB RLS + 미들웨어 + UI 3계층 모두 필요
Rate Limiting무차별 요청으로 서버 과부하Upstash Redis / Cloudflare로 구현
bcrypt비밀번호 단방향 해시평문 저장 절대 금지 / Supabase Auth 자동 처리

인프라·실전

개념한 줄 정의왜 중요한가
CDN + Cloudflare가까운 서버에서 파일 전달 + DDoS 방어속도↑ / Vercel 과금 폭탄 방지
PWAmanifest + service worker → 홈화면 설치형 앱앱스토어 없이 모바일 앱 배포
CI/CDgit push → 자동 테스트 → 자동 배포수동 배포 실수 제거
Docker컨테이너로 어디서든 동일 실행 환경"내 컴엔 됐는데" 문제 해결
도메인·DNSA·CNAME·MX 레코드로 서버 연결실서비스 배포의 필수 과정
모니터링 (Sentry·PostHog)에러·사용자 행동 자동 추적배포 후 문제를 알 방법
결제 (Stripe·Toss)PCI DSS 대응 외부 결제 처리직접 구현은 보안 인증 불가

AI · Agent · 바이브코딩

개념한 줄 정의실전 포인트
MCPAI가 외부 도구·DB·API에 연결하는 표준Supabase·GitHub·Vercel MCP로 자동화
SkillAI에게 도메인 지식을 주입하는 패키지anthropics/skills가 공식 라이브러리
CLAUDE.mdAI 에이전트에게 프로젝트 컨텍스트 파일이 파일 하나로 실수 40~60% 감소
Context EngineeringAI에게 필요한 정보만 정확히 전달하는 기술2026년 핵심 스킬 — 프롬프트 길이보다 정확도
바이브코딩 취약점이해 없는 작동·보안 구멍·패턴 불일치 등4단계 방어선(CLAUDE.md·세션규칙·배포전체크·월간점검)
다음 단계: 개념을 이해했다면 실제로 작은 것이라도 만들어보세요. 이해와 경험은 완전히 다릅니다. 막히는 순간이 진짜 배움의 시작입니다.
Section 08 / 09
SECTION 09
실전 응용 · 기초

AI Agent와 함께 개발하기

개념을 알았다면 이제 AI와 함께 빠르게 만드는 법을 익힐 차례입니다.

바이브코딩의 핵심 자세: AI에 모든 걸 맡기는 것이 아닙니다. "스스로 시스템을 구축하는 체력"을 기르는 것이 진짜 목표입니다. 막혔을 때 포기하지 않고 다시 시도하는 자세, 작은 성공을 쌓아가는 인내, AI의 출력을 검증하는 비판적 사고. 도구는 도와줄 뿐, 만드는 사람은 당신입니다.

AI Agent와 개발할 때 유념할 5가지

원칙설명
1. 컨텍스트가 전부AI는 보여준 정보만 안다. 폴더 구조·기존 코드·요구사항을 충분히 보여줘야 함
2. 작은 단위로 쪼개기한 번에 5개 수정보다 1개씩 5번이 정확하다. 큰 작업은 P0→P1→P2 단계별로
3. 검증 단계 명시"수정 후 Playwright로 스크린샷 찍어 보여줘" 같이 결과 확인 방법 같이 지시
4. 추측 금지 요청"토큰이나 컴포넌트에 없는 요소가 있으면 무조건 물어보고 진행해라"
5. 컨텍스트 관리대화가 길어지면 /compact 또는 새 세션으로. 70% 초과 시 같은 실수 반복
핵심: AI Agent는 "지시 받는 대로 일하는 새 팀원"입니다. 신입에게 일을 맡기듯 — 맥락·기대·검증 방법을 같이 알려줘야 좋은 결과가 나옵니다.

효과적 프롬프트 — 추상 vs 측정 가능

❌ 추상적 (실패)
"확 달라보이게 해줘"
"예쁘게"
"잘 작동하게"
"버그 고쳐줘"
✅ 측정 가능 (성공)
"카드 padding 16px, gap 12px로"
"768px 미만에서 sidebar→bottom-nav"
"Lighthouse 90+ 달성"
"콘솔 에러 첨부: [내용] 원인 파악·수정"

프롬프트 4대 구성 요소

좋은 프롬프트 템플릿
[역할 / 컨텍스트] 너는 Next.js 15 + TypeScript + Tailwind 전문가다. 이 프로젝트는 사내 업무 도구이고, shadcn/ui 컴포넌트를 사용한다. [목표 — 측정 가능하게] 대시보드 페이지에 부서별 보고서 수를 Bar Chart로 표시하라. - recharts 사용 - 모바일에서 카드 형태로 fallback - 데이터는 /api/reports/stats 에서 fetch [제약] - DESIGN.md 토큰 따라 색상 적용 - 토큰·컴포넌트 없는 요소는 먼저 질문할 것 - 이번 작업은 차트만, 다른 페이지 건드리지 말 것 [검증] 완료 후 모바일·데스크톱 스크린샷 찍어 보여줘.
2026년 트렌드 — 컨텍스트 엔지니어링: 2026년 LLM 작업의 핵심 스킬은 더 이상 "긴 프롬프트 작성"이 아니라 "정확한 컨텍스트 제공". 검색·압축·구조화로 모델에게 필요한 정보만 효율적으로 전달하는 것이 중요합니다.

AGENTS.md / CLAUDE.md — AI에게 프로젝트 컨텍스트 주는 표준

AGENTS.md는 엔지니어링 팀이 AI 코딩 에이전트에게 컨벤션과 컨텍스트를 전달하는 사실상의 표준이 되었습니다. Anthropic 내부 벤치마크 기준 컨텍스트 파일이 있을 때 잘못된 패턴으로 다시 작성하는 비율이 40~60% 감소합니다.

CLAUDE.md / AGENTS.md 구조 예시
# 프로젝트 소개 사내 업무 자동화 도구. Next.js 15 + Supabase + Vercel. # 디자인 원칙 - 정보 밀도 우선, 화려한 효과 금지 - rounded-2xl 이상 금지, shadow-md까지만 - 색상: 회색 베이스 + 포인트 1색 # 코딩 컨벤션 - 컴포넌트: src/components/ - 비즈니스 로직: src/lib/ - API: app/api/ # 작업 규칙 - 토큰·컴포넌트에 없는 요소는 먼저 질문 - 한 번에 한 파일만 수정 - 변경 후 Playwright 검증

주요 AI 코딩 도구 비교 (2026년 5월 기준)

도구특징가격적합한 경우
Claude Code터미널 기반 에이전트. 1M 토큰 컨텍스트. 코드 품질 1위$17~$200/월대규모 리팩토링, 복잡한 다중 파일 작업
CursorVS Code 포크. IDE 통합 최고. 인라인 편집 빠름$20/월~일상 코드 편집, IDE에서 작업 선호
OpenAI Codex샌드박스 VM, 비동기 PR. 토큰 효율 높음$20/월~장기 자율 작업, 백그라운드 리팩토링
GitHub CopilotVS Code 확장, 자동완성 강점$10/월~코드 자동완성 위주
WindsurfAI-first IDE, 무료 티어 있음무료~가볍게 시작
실측 성능: 동일 작업에서 Claude Code(Opus)가 33K 토큰으로 완료한 것을 Cursor(GPT-5)는 188K 토큰을 사용하고 에러까지 발생. 도구별 토큰 효율 차이가 큽니다.
현실적 조합: 한 도구만 쓰지 않습니다. 일상 편집 = Cursor, 복잡한 리팩토링 = Claude Code, 자동완성 = Copilot 식으로 워크플로마다 다른 도구 활용.

바이브코딩의 취약점 — 알고 써야 한다

AI와 함께 빠르게 개발하는 것과, 오래 작동하는 코드를 만드는 것은 다릅니다. 바이브코딩은 "지금 작동함"을 최적화하는 방식이라, 방치하면 아래 문제가 누적됩니다.

취약점증상위험도
이해 없는 작동왜 동작하는지 모름 → 에러 루프 반복★★★★★
보안 구멍RLS 누락, 인증 없는 API, 환경변수 노출★★★★★
패턴 불일치세션마다 다른 폴더·네이밍·스타일 혼재★★★★
에러 처리 누락해피 패스만 있고 에러·빈 상태 시 흰 화면★★★★
성능 시한폭탄10명엔 괜찮지만 1만 명이면 DB 다운★★★★
타입 형해화TypeScript 쓰지만 any·as 남발로 타입 안전성 0★★★
컨텍스트 단절긴 대화 후 AI가 앞 기준 잊고 같은 실수 반복★★★
가장 위험한 패턴: 빠르게 만든 것이 빠르게 죽습니다. Phase 1(빠른 개발) → Phase 2(기능 추가, 점점 느림) → Phase 3(고치면 다른 곳 깨짐) → Phase 4(AI도 전체 파악 불가) → Phase 5(처음부터 재개발). 예방이 유일한 해결책입니다.

4단계 방어선 — 취약점 보완 가이드

🟦 1단계 — 시작 전: CLAUDE.md 구조 잡기

프로젝트 루트에 CLAUDE.md를 두면 AI 세션이 달라져도 같은 기준으로 작업합니다. Anthropic 내부 벤치마크 기준 이 파일 하나로 실수가 40~60% 감소합니다.

CLAUDE.md 필수 포함 항목
# 프로젝트명 ## 스택 Next.js 15 App Router + TypeScript strict Supabase (DB + Auth + Storage) + Vercel ## 폴더 구조 (임의 변경 금지) src/ ├── app/ ← 페이지·API Route ├── components/ ← 공통 컴포넌트 │ ├── ui/ ← shadcn 원본 │ └── custom/ ← 커스텀 ├── lib/ ← 비즈니스 로직 ├── hooks/ ← 커스텀 훅 └── types/ ← TypeScript 타입 ## 네이밍 규칙 컴포넌트 : PascalCase (UserCard.tsx) 함수·변수 : camelCase (getUserById) 상수 : UPPER_SNAKE (MAX_RETRY) DB 테이블 : snake_case (user_profiles) ## 코딩 규칙 - any 사용 금지 - as 강제 캐스팅 금지 - console.log 배포 코드 금지 - 한 번에 한 파일만 수정 ## 보안 필수 (매 작업 후 확인) - 모든 API Route에 인증 검증 - Supabase RLS 정책 적용 - 환경변수 클라이언트 노출 금지 - Rate Limiting 적용 ## AI 규칙 - 토큰·컴포넌트에 없는 요소 → 먼저 질문 - 새 패턴 도입 전 기존 패턴 확인 후 통일 - 작업 후 반드시 에러 케이스 처리 포함

🟩 2단계 — 개발 중: 세션 규칙

세션 시작 / 작업 요청 / 종료 패턴
【세션 시작 시】 CLAUDE.md 읽고 시작해. 현재 폴더 구조 파악 후, 새로 만들기 전에 재사용 가능한 컴포넌트·함수가 있는지 먼저 알려줘. 【작업 요청 시 — 4가지 포함】 목표: /dashboard에 사고 건수 Bar Chart 추가 (recharts 사용) 제약: 기존 컴포넌트·토큰 변경 금지. 다른 파일 건드리지 말 것. 에러처리: Loading=Skeleton / Error=인라인 재시도 / Empty=안내 문구 검증: 모바일(375px)·데스크톱(1280px) 스크린샷 첨부 【세션 종료 전】 이번 세션에서 변경된 파일 목록 보여줘. 추가된 패키지 있으면 알려줘. 보안 체크리스트 중 빠진 항목 있으면 알려줘. 【컨텍스트 70% 초과 시】 /compact 요약 후 현재까지 결정 사항과 다음 작업 목록 알려줘.

🟥 3단계 — 배포 전: 체크리스트

구분체크 항목확인 방법
🔴 보안
(필수)
모든 API Route 인증 검증코드 직접 확인
Supabase RLS 전 테이블 적용Supabase 대시보드
.env.local → .gitignore 포함git status 확인
NEXT_PUBLIC_ 에 비밀 키 없음환경변수 목록 검토
로그인 API Rate Limiting코드 확인
🟡 품질
(권장)
TypeScript 빌드 에러 0개npm run build
Loading·Error·Empty 3상태 처리화면 직접 확인
콘솔 에러 없음DevTools Console
모바일 375px 레이아웃 정상Chrome 기기 시뮬레이터
🟢 성능
(이후)
Lighthouse 모바일 80+Chrome Lighthouse
주요 쿼리 인덱스 적용EXPLAIN ANALYZE
이미지 next/image 사용코드 확인

🟪 4단계 — 운영 중: 월 1회 점검 프롬프트

월간 코드 건강 점검
전체 코드베이스 스캔해서 다음 항목 보고해줘. 수정은 하지 말고 목록만 작성할 것. 1. any 타입 사용된 곳 목록 2. 인증 없는 API Route 목록 3. 에러 처리 없는 async 함수 4. 중복된 컴포넌트·함수 5. 사용되지 않는 import 6. TODO 주석 목록 7. console.log 남은 곳 8. 하드코딩된 값 (색상·URL·문자열)

취약점별 예방 프롬프트 한 줄 카드

이해 없는 작동
"이 코드가 왜 이렇게 동작하는지 3줄로 설명해줘"
보안 구멍
"보안 체크리스트 기준으로 이 코드 취약점 찾아줘"
에러 처리 누락
"Loading / Error / Empty 3가지 상태 모두 처리해줘"
패턴 불일치
"기존 컴포넌트 패턴 확인 후 통일해줘"
성능 시한폭탄
"이 쿼리가 100만 건에서도 빠를지 확인해줘"
타입 형해화
"any 없이 타입 정의해줘. as 캐스팅 금지"
컨텍스트 단절
"CLAUDE.md 읽고 시작해. 규칙 어긴 부분 먼저 알려줘"
기능 추가 전
"새로 만들기 전에 재사용 가능한 게 있는지 먼저 확인해줘"
핵심 원칙: AI는 "지금 작동하는 것"을 만들고, 당신은 "계속 작동할 것"을 책임집니다. 바이브코딩의 한계는 사용자의 이해 수준만큼 올라갑니다.

AI가 3번 이상 같은 코드로 실패할 때 — 루프 탈출 행동 강령

AI가 에러를 못 고치고 같은 코드를 반복 생성하는 "AI 루프"는 바이브코딩에서 가장 흔한 좌절 포인트입니다. 이 체크리스트를 따르면 90% 이상 탈출 가능합니다.

#행동AI에게 줄 지시 예시
1범위 좁히기 — "무엇이 문제인가"를 먼저 물어라"지금 이 에러의 근본 원인을 고치기 전에 원인이 무엇인지 3가지로 설명해줘. 코드 수정은 하지 마."
2console.log 심기 — 실제 값이 무엇인지 확인"이 함수 안에 console.log를 추가해서 실제로 어떤 값이 들어오는지 확인할 수 있게 해줘. 수정은 그다음에."
3최소 재현 코드 격리 — 복잡한 코드에서 문제 부분만 분리"이 버그를 재현할 수 있는 가장 단순한 코드 10줄로 만들어줘."
4접근 방식 변경 지시 — 같은 방법 반복 금지"지금까지 시도한 방법은 모두 실패했어. 완전히 다른 접근법으로 처음부터 다시 설명해줘."
5새 대화 시작 — 컨텍스트 오염 초기화새 Claude Code 세션 시작 → 문제 파일·에러·시도한 방법 정리해서 붙여넣기
6공식 문서로 우회 — AI 대신 원본 찾기Next.js·Supabase 공식 docs에서 관련 API 직접 검색 → 정확한 파라미터를 AI에게 제공
AI 루프 탈출 프롬프트 템플릿
# AI가 3번 실패했을 때 이 형식으로 새로 물어보기 지금까지 이 문제를 3번 시도했지만 계속 실패했어. [문제 설명] ○○ 기능을 구현하려는데 계속 ○○ 에러가 발생함 [시도한 방법 3가지] 1. ... 2. ... 3. ... [에러 메시지 전체] (콘솔 에러 붙여넣기) [현재 관련 코드] (문제 파일 붙여넣기) 이제 새로운 접근법으로 원인 분석부터 해줘. 코드 수정은 원인 파악 후에 시작해.
루프가 지속되면 의심해야 할 것: 버전 충돌 (package.json 확인), 환경변수 누락 (.env.local 확인), 브라우저 캐시 (Cmd+Shift+R 강제 새로고침), Node 모듈 손상 (node_modules 삭제 후 npm install 재실행)
실전 응용 · 심화

MCP · Skills · 최신 생태계

AI Agent를 외부 도구·데이터와 연결하는 표준입니다.

MCP — Model Context Protocol

2024년 Anthropic이 만든 개방형 표준. AI 어시스턴트(Claude·Cursor 등)가 외부 도구·데이터베이스·API에 표준화된 프로토콜로 접근하는 방식입니다. 2026년 5월 기준 70+ 공식 서버, 1200+ 커뮤니티 서버 존재.

MCP 없을 때
AI가 GitHub, DB, Slack 등 외부 정보 모름
→ 사용자가 매번 복사·붙여넣기로 정보 전달
MCP 사용 시
AI가 "Issue 목록 가져와", "DB 조회해"라고 하면 자동 처리
→ 환각 감소, 자동화 수준 ↑

꼭 알아둘 MCP 서버 12선

카테고리MCP 서버역할
개발GitHub MCP저장소·이슈·PR 조회·생성
Playwright MCP브라우저 자동화·스크린샷·UI 테스트
JetBrains MCPIDE 안의 코드·디버그 정보 접근
DB·데이터Supabase MCPPostgres 조회·스키마 변경·RLS
MongoDB MCPNoSQL 조회·집계
Chroma / Qdrant MCP벡터 DB (RAG용 임베딩)
인프라Vercel MCP배포 상태·로그·환경변수
Cloudflare MCPDNS·Workers·R2 관리
검색·웹Tavily / Brave Search MCP실시간 웹 검색
Firecrawl MCP웹페이지 크롤링·마크다운 변환
생산성Notion / Linear MCP문서·이슈 트래커 통합
Slack MCP메시지 조회·발송
설치 방식: HTTP/SSE 원격 서버는 URL만 등록하면 바로 사용 가능. STDIO 로컬 서버는 npm/pip로 설치 후 설정 파일에 등록. 2026년 들어 원격 MCP 생태계가 폭발적으로 성장 — 1월 16개에서 4월 25개+로 늘어났고 Atlassian·HubSpot·Linear·Sentry·Neon·Vercel 등이 모두 원격 엔드포인트를 출시했습니다.

⚠️ 이 섹션은 Claude Code 사용자 전용입니다. Claude Code를 설치하고 터미널에서 사용하는 경우에 해당합니다. claude.ai 웹 채팅만 사용한다면 Skills가 아닌 위의 MCP를 참고하세요.

Skills — AI에게 도메인 전문성 패키지로 주기

Skill은 SKILL.md + 보조 스크립트·문서를 묶은 폴더입니다. Claude Code가 작업 상황에 맞는 Skill을 자동 감지해서 로드합니다. 전체 생태계는 1,000+개이며 Anthropic 공식 17개는 출발점에 불과합니다.

MCP
외부 시스템 연결
DB·API·SaaS 접근 프로토콜
예: Supabase 조회, GitHub PR 생성
Skill
도메인 전문성 주입
특정 작업 수행 방법 패키지
예: docx 생성, Next.js 패턴, 보안 리뷰
Progressive Disclosure: 세션 시작 시 각 Skill 이름·설명만 ~100토큰 로드. 작업에 필요하다고 판단될 때만 본문(~5,000토큰) 추가 로드. 수백 개를 설치해도 컨텍스트 부담 없음.

🔧 설치 방법 3가지

Claude Code에서 Skills 설치
# ① 전체 Anthropic 공식 Skills 한 번에 설치 git clone https://github.com/anthropics/skills ~/.claude/skills-repo ln -s ~/.claude/skills-repo/skills ~/.claude/skills # ② npx로 특정 Skill만 선택 설치 npx skills add anthropics/claude-code --skill frontend-design npx skills add anthropics/claude-code --skill pdf # ③ CLAUDE.md에서 경로 직접 지정 # /mnt/skills/public/ 같은 경로를 CLAUDE.md에 명시

📦 Anthropic 공식 Skills 17개

모두 무료·오픈소스. github.com/anthropics/skills에서 소스 확인 후 설치.

문서 생성 4종 — 가장 먼저 설치

Skill하는 일
pdfPDF 생성·편집·텍스트·표 추출 (전체 최다 사용)
docx스타일·표·변경추적 포함 Word 문서 생성·편집
xlsx수식·피벗·서식 포함 Excel 생성·분석
pptx슬라이드 마스터·차트·이미지 포함 PPT 덱 생성

디자인·브랜딩 4종

Skill하는 일
frontend-designReact·Tailwind·접근성·반응형 패턴. 277,000+ 설치
brand-guidelines브랜드 색상·폰트·보이스 전체 산출물에 일관 적용
canvas-design레이어·타이포·간격 포함 2D 캔버스 비주얼 구성
theme-factory색상 팔레트·타이포·컴포넌트 스타일 세트 생성

엔지니어링 5종

Skill하는 일
webapp-testingPlaywright 테스트 작성·헤드리스 실행 — "만들었지만 검증 안 한" 약점 보완
web-artifacts-builder빌드 스텝 없이 어디서나 실행되는 HTML/JS 자립형 아티팩트
mcp-builderMCP 서버 스캐폴딩 — 내부 DB·API·SaaS 연결 서버 생성 가이드
claude-api인증·스트리밍·툴 유즈·비전·배치·프롬프트 캐싱 등 Anthropic API 패턴
algorithmic-artp5.js 기반 파라메트릭·절차적 아트워크 생성

커뮤니케이션 3종 + 메타 1종

Skill하는 일
doc-coauthoring변경 추적·보이스 유지·제안 방식 긴 문서 공동 편집
internal-comms전사 업데이트·상태 보고서·공지·FAQ 형식·톤 표준화
slack-gif-creatorSlack 반응 및 인라인 답글용 커스텀 애니메이션 GIF
skill-creator ⭐내 팀의 반복 워크플로를 커스텀 Skill로 만드는 메타 스킬. 기본기 익히고 나면 최고 레버리지

🤝 파트너 공식 Skills — 바이브코더 필수 모음

Vercel·Supabase·Stripe 등 주요 플랫폼이 직접 제공하는 공식 Skills. 최신 베스트 프랙티스가 반영됩니다.

Next.js · React (Vercel Labs 공식)

Skill하는 일
vercel-labs/next-best-practicesNext.js 베스트 프랙티스 및 권장 패턴
vercel-labs/react-best-practicesReact 베스트 프랙티스 및 패턴
vercel-labs/composition-patterns복합 컴포넌트·재사용 패턴 (compound components, React 19+ 패턴)
vercel-labs/web-design-guidelinesARIA·포커스·터치 타겟·시맨틱 HTML 등 UI 품질 게이트
vercel-labs/next-cache-componentsNext.js 캐싱 전략·캐시 인식 컴포넌트
vercel-labs/next-upgradeNext.js 버전 업그레이드 워크플로

DB · 백엔드

Skill하는 일
supabase/postgres-best-practicesSupabase PostgreSQL 베스트 프랙티스
neondatabase/neon-postgresNeon Serverless Postgres 베스트 프랙티스
stripe/stripe-best-practicesStripe 통합 베스트 프랙티스
stripe/upgrade-stripeStripe SDK·API 버전 업그레이드

인증

Skill하는 일
better-auth/best-practicesBetter Auth 통합 베스트 프랙티스
better-auth/create-authBetter Auth 인증 셋업 생성
better-auth/emailAndPassword이메일·비밀번호 인증
better-auth/twoFactor2단계 인증
better-auth/organization조직 관리

인프라 · 배포

Skill하는 일
cloudflare/workers-best-practicesCloudflare Workers 프로덕션 베스트 프랙티스
cloudflare/wranglerWorkers·KV·R2·D1·Vectorize·Queues 배포·관리
cloudflare/web-perfCore Web Vitals 감사·렌더 블로킹 리소스
netlify/netlify-functions서버리스 API 엔드포인트·백그라운드 태스크
netlify/netlify-deployNetlify 배포 자동화 워크플로

모니터링 · 보안

Skill하는 일
getsentry/sentry-nextjs-sdkNext.js 13+ (App Router) Sentry SDK 완전 셋업
getsentry/sentry-workflow프로덕션 이슈 발견·수정 엔드투엔드 워크플로
getsentry/sentry-sdk-setup모든 언어·프레임워크에서 Sentry 자동 감지 설치
trailofbits/static-analysisCodeQL·Semgrep·SARIF 정적 분석 툴킷
trailofbits/insecure-defaults하드코딩 시크릿·기본 자격증명·취약 암호화 감지
trailofbits/modern-pythonuv·ruff·ty·pytest 모던 Python 툴링

협업 · 생산성

Skill하는 일
openai/yeetstage·commit·push·GitHub PR 열기 CLI
openai/gh-fix-ci실패한 GitHub Actions PR 체크 디버그·수정
openai/playwright브라우저 자동화·폼·스크래핑 실제 인터랙션
firecrawl/firecrawl-build웹 검색·스크래핑·추출·브라우저 인터랙션 통합

📍 어디서 더 찾을까 — 1,000+ Skills 탐색

출처특징
officialskills.sh공식 Skills 전체 검색 포털. 팀별·카테고리별 정렬. 월 30만 뷰
VoltAgent/awesome-agent-skills21,600+ stars. Anthropic·Vercel·Stripe·Cloudflare·Expo 등 40+ 팀 공식 Skills 1,000+개. 크로스 플랫폼 (Claude/Cursor/Codex/Gemini)
travisvn/awesome-claude-skillsClaude Code 중심 큐레이션. 가장 잘 정리된 목록
ComposioHQ/awesome-claude-skills도메인별 분류 (법무·마케팅·엔지니어링)
sickn33/antigravity-awesome-skills1,400+ Skill. Claude·Cursor·Codex·Gemini 모두 지원
Park님 스택 추천 설치 순서:
1. anthropics/skills 전체 클론 → 즉시 17개 활성화
2. vercel-labs/next-best-practices + vercel-labs/react-best-practices
3. supabase/postgres-best-practices
4. getsentry/sentry-nextjs-sdk
5. 반복 워크플로 발견 시 skill-creator로 커스텀 Skill 직접 제작

AI-DLC — AI 주도 개발 라이프사이클

AWS가 2025년 10월 공식 발표한 새로운 소프트웨어 개발 방법론. 기존 SDLC를 "AI 시대"에 맞게 재설계한 것으로, AI가 워크플로를 주도하고 인간은 승인자·검증자 역할로 전환합니다.

바이브코딩
"로그인 페이지 만들어줘"
→ AI가 추측해서 생성
→ "아니, 그게 아니야"
→ 무한 반복 (정의된 '완성'이 없음)
스펙 주도 개발
PRD 작성 → 핸드오프
→ 작성자와 구현자의 정신모델 차이
→ 해석 차이가 리뷰 시점에 드러남
→ 격차 메우는 왕복 작업
AI-DLC
인간 + AI가 스펙을 공동 창조
→ 동일 시스템이 스펙도 만들고 구현도 함
→ 핸드오프 = 0, 해석 차이 = 0
→ 측정 가능한 기준이 AI 자율성을 결정
핵심 통찰 — Autonomy = f(Criteria Clarity): AI의 자율성은 기준의 명확도에 정비례합니다. "예쁘게 만들어줘" → AI가 계속 묻게 됨 / "WCAG AA 명도비 4.5:1, p95 200ms 이내" → AI가 스스로 검증하며 자율 작업.

3단계 워크플로 — Inception → Construction → Operations

1
Inception (착수) — Mob Elaboration비즈니스 의도 → 요구사항·스토리·유닛으로 AI가 변환. 팀 전체가 모여 3-4시간 동안 AI의 질문·제안을 실시간 검증·세련화
2
Construction (구축) — Mob Construction검증된 맥락 사용. AI가 아키텍처·도메인 모델·코드·테스트 제안. 3-5일 대면 구현 의식. 팀이 결정·아키텍처 선택을 실시간으로 설명
3
Operations (운영)AI가 텔레메트리 분석·이상 감지·SLA 위반 예측. 인시던트 런북 통합. 개발자가 승인하면 솔루션 자동 실행

새로운 용어 — 애자일 용어를 AI 시대에 맞게 재정의

새 용어기존 용어 대체의미
Bolt (볼트)스프린트 (주 단위)시간·일 단위 집중 작업 주기. AI 컨텍스트 윈도우 한 세션. 메모리 가득 차면 파일로 저장 후 새 세션에서 이어서 작업
Unit (유닛)에픽독립적으로 실행 가능한 작업 단위. 의존성 그래프(DAG)로 연결되어 병렬 실행 가능
Hat (해트)역할(Role)신선한 AI 에이전트에게 주입되는 역할 명세. Planner·Builder·Reviewer·Designer 등 14가지
Mob Elaboration요구사항 정의 회의팀+AI가 한 방에 모여 의도→유닛으로 협력 분해하는 의식
Mob Construction구현 스프린트대면 환경에서 AI 출력을 실시간 검증·결정하는 구현 의식

5가지 워크플로 — 작업 유형에 맞게 선택

워크플로해트 순서용도
DefaultPlanner → Builder → Reviewer일반 기능 개발 (가장 흔함)
AdversarialPlanner → Builder → Red Team → Blue Team → Reviewer보안 중요한 기능 (인증·결제)
TDDTest Writer → Implementer → Refactorer → Reviewer테스트 우선 개발
DesignPlanner → Designer → ReviewerUI/UX 설계 (와이어프레임·디자인 토큰)
HypothesisObserver → Hypothesizer → Experimenter → Analyst버그 디버깅 (가설 검증)

3중 루프 구조 — 큰 흐름에서 작은 단위까지

외부 루프
Assembly Line
유닛이 의존성 그래프를 따라 흐름. 독립 유닛은 병렬 실행
중간 루프
Hat Rotation
유닛 내에서 Plan → Build → Review 사이클 반복
내부 루프
Bolt (컨텍스트 복구)
메모리 부족 시 파일로 상태 저장 → 새 세션에서 이어서

품질 게이트 3가지 — AI가 건너뛸 수 없는 검문소

게이트규칙자동 감지
Plan Gate"청사진 없이 빌드 금지" — Planner가 계획 저장해야 Builder 시작
Quality Gate"깨진 코드 리뷰 금지" — 테스트·타입·린트 모두 통과해야 Reviewer 단계로package.json → npm test / pyproject.toml → pytest / Cargo.toml → cargo test
Criteria Gate"증거 없이 출하 금지" — 모든 성공 기준이 구체적 증거로 검증되어야 유닛 완료

9단계 엘라보레이션 대화 — 계획 단계의 실제 흐름

/ai-dlc:elaborate 대화 예시
# 약 10분, 9번의 주고받음으로 끝남 1. AI: "뭘 만들고 싶어요?" 2. AI: "더 자세히 — 누가 쓰나? 어떤 OAuth 제공자?" 3. Discovery Agent가 코드베이스 탐색 (자동) 4. AI: "발견한 도메인 모델 — User, OAuth Token, Session" 5. AI: "어떤 워크플로? Default 추천" 6. AI: "성공 기준 3-7개 정의 — 측정 가능한 것만" 7. AI: "4개 유닛으로 분해. 2,3은 병렬, 4는 2,3 이후" 8. AI: "어떻게 전달? 유닛별 PR / 한 번에 / main 직접" 9. AI: "준비 완료. 빌드 시작?" # 이후 /ai-dlc:execute로 자율 빌드 시작

도구 — AI-DLC를 실제로 쓰는 방법

도구공급특징
Amazon Q DeveloperAWS 공식프로젝트 규칙 기반 AI 코딩 도구. AI-DLC 권장 도구
KiroAWS 공식스펙 주도 AI IDE. 프롬프트 → 상세 스펙 → 작동하는 코드·문서·테스트
ai-dlc.dev 플러그인The Bushido Collective (MIT)오픈소스 구현. Claude Code에 설치하면 /ai-dlc:elaborate 등 명령어 사용
바이브코딩과의 관계 — 다음 단계로 가는 길:
바이브코딩(개인 단위) → AI-DLC(조직 단위). 본질은 같음 — 컨텍스트 엔지니어링(CLAUDE.md), AI에게 정확한 지시, 측정 가능한 기준 설정. 바이브코딩으로 익힌 기본기가 그대로 AI-DLC의 토대가 됩니다. 큰 시스템을 팀과 만들 때 필요한 방법론.
지금 적용할 수 있는 3가지:
1. 측정 가능한 성공 기준: "빠르게" → "p95 200ms 이내" 같이 검증 가능한 표현으로
2. 유닛 분해: 큰 기능을 의존성 그래프로 작은 유닛으로 쪼개기
3. Plan → Build → Review 사이클: 한 번에 다 만들지 말고 계획 → 구현 → 검증 반복
용어집
검색 결과가 없습니다