1부 · 기술 기초
0강. 러닝 예시 — 이벤트 RSVP 서비스
이 강의 목적: 이 교재는 처음부터 끝까지 하나의 서비스를 예시로 사용합니다. 바로 사내 이벤트 RSVP 서비스입니다. 각 강은 이 서비스를 다시 설명하지 않고 여기(0강)를 참조합니다. 먼저 이 서비스가 무엇인지 한 번 읽어두면, 이후 모든 강의 프론트엔드·백엔드·데이터·인프라·자동화 설명이 하나의 구체적인 그림 위에서 이어집니다.
1. 서비스 개요
무엇을 하는 서비스인가. 사내·동호회 이벤트의 신청·취소·정원 관리(RSVP는 '회신 바랍니다'라는 뜻의 프랑스어 Répondez s'il vous plaît의 약자입니다)를 온라인으로 처리하는 작은 서비스입니다. 지금까지 신청이 카카오톡 단체방에서 이뤄져 명단 추적·취소 확인·정원 파악이 어려웠던 문제를 해결합니다.
누가 쓰는가. 주최자(HR·팀장)는 이벤트를 개설하고 명단을 조회하고 정원을 변경합니다. 참석자(직원·회원)는 신청하고 취소하고 일정을 확인합니다.
핵심 기능(MVP). 이벤트 생성 · 참석 신청(이름·이메일·참석 여부) · 주최자 명단 조회 · 참석자 신청 취소 · 정원 변경입니다.
하지 않을 것(V2 이후). 결제 · 대기열 · 좌석 배치도 · SNS 공유 · 푸시 알림은 초기 범위에서 제외합니다.
성공 지표(예). 출시 2주 내 가입 100명 · 월 5회 이상 개설 · 신청 프로세스 1분 이내입니다.
1.1 만들 화면 미리보기
말보다 그림이 빠릅니다. 이 서비스로 실제 만들 화면은 크게 네 개입니다. 아래는 실제 화면이 아니라 "무엇을 만들지" 감을 잡기 위한 대략적 와이어프레임입니다.

참석자는 ① 이벤트 목록에서 관심 이벤트를 고르고 ② 상세 화면의 신청 폼으로 참석을 신청하며, ③ 내 신청 화면에서 확인·취소합니다. 주최자는 ④ 대시보드에서 신청 현황과 명단을 보고 정원을 조정합니다. 이 네 화면을 기준으로 이후 강의 프론트엔드·백엔드·데이터 설명이 이어집니다.
2. 아키텍처 한눈에
이 서비스를 프론트엔드·백엔드·데이터·인프라 네 계층으로 나눠 정리하면 다음과 같습니다. 각 계층의 구체적인 원리는 기술 기초 파트(2~5강)에서 이 서비스를 예시로 풀어갑니다.
프론트엔드. Next.js + React + TypeScript로 만들고, Tailwind CSS + shadcn/ui로 스타일링하며, 폰·태블릿·PC를 아우르는 반응형 웹입니다. 페이지 성격에 따라 렌더링 전략을 다르게 씁니다 — 회사 소개·이벤트 상세는 SSG(+시간당 ISR), 이벤트 목록은 SSR, 신청 폼·대시보드는 CSR, 개인 신청 내역은 SSR입니다. 대표 화면은 이벤트 목록, 이벤트 상세+신청 폼, 신청 확인/내 신청, 주최자 대시보드 네 개입니다.
백엔드. Python FastAPI(대안 Node.js/NestJS)로 REST API를 제공합니다(예: /api/v1/events/{id}/rsvp). 인증·권한은 JWT + RBAC로, 역할은 일반 참석자·이벤트 호스트·관리자 셋입니다. 비즈니스 규칙은 반드시 백엔드가 강제합니다 — 마감(400), 정원 초과(409), 중복 신청(409), 종료 후에는 조회만입니다. 동시 신청은 트랜잭션 + 행 잠금(ACID)으로 오버부킹을 막습니다. 운영 측면에서는 캐싱(Redis)·이메일 비동기 큐·로드밸런싱·로깅/모니터링을 두고, 배포는 Docker + CI/CD로 합니다.
데이터. PostgreSQL(정규화)을 쓰되, MVP는 Supabase(BaaS)로 시작해 규모가 커지면 자체 스택으로 옮깁니다. 테이블은 네 개입니다 — users(id·email·name), events(id·title·capacity·created_by·scheduled_at), rsvps(id·user_id·event_id·status·created_at), admins(user_id·event_id·permission). 접근은 RLS(행 단위)로 통제합니다. 사용자는 본인 행, 호스트는 담당 이벤트, 관리자는 전체를 봅니다. 파일은 성격에 따라 나눕니다 — 포스터는 S3 + CDN(공개), 개인 증명 PDF는 S3(비공개) + 서명된 URL, 당일 사진은 S3(관리자만)입니다.
인프라·배포·보안. 프론트는 Vercel(PaaS), DB는 Supabase(BaaS)에 자동 CI/CD로 배포합니다. 도메인은 rsvp.ourcompany.com(A 레코드)이고 HTTPS는 Let's Encrypt로 자동 발급됩니다. 시크릿은 배포 플랫폼의 환경 변수 패널에 두고(코드·Git에 두지 않음) 주기적으로 회전합니다. 보안은 매개변수화 쿼리·이스케이프·SameSite 쿠키·MFA의 다층 방어로, 모니터링은 Sentry+분석에서 Slack 알림으로 잇습니다. 개인정보는 동의 체크와 처리방침(수집·목적·보관기간 30일 명시)을 두고 PIPA/GDPR를 고려합니다.
3. 강별로 RSVP의 어떤 면을 쓰나
| 파트 · 강 |
RSVP를 이렇게 활용 |
| 기술 기초 2강 프론트엔드 |
목록 페이지 목업(세 계층), 화면별 정적/동적·렌더링 모드·스택 선택 |
| 기술 기초 3강 백엔드 |
다섯 책임, API 명세, JWT+RBAC 권한 매트릭스, 규칙 4관문, 트랜잭션 오버부킹 |
| 기술 기초 4강 데이터 |
데이터 4종류, ERD(4테이블), 정규화, 객체 스토리지+CDN, RLS 정책, 데이터 흐름 |
| 기술 기초 5강 인프라·배포·보안 |
4계층·클라우드·DNS·HTTPS·보안 위협·시크릿·모니터링·법규·인프라 구성 |
| 코딩 with Claude 초급 4강 |
Cowork으로 RSVP 웹앱을 만드는 전체 워크플로우(생성→DB→배포) |
| 코딩 with Claude 중급·고급 |
커맨드·서브에이전트·hooks·MCP·품질 게이트·멀티에이전트를 RSVP 운영에 적용 |
이제 이 서비스를 머릿속에 두고, 기술 기초 파트부터 시작합니다. 개발을 몰라도 괜찮습니다. 각 강이 이 RSVP 서비스를 하나씩 뜯어보며 "화면 뒤에서 무슨 일이 벌어지는가"를 설명합니다.
1부 · 기술 기초
입문(기술 기초) 2강. 프론트엔드
유형: 이론 (다이어그램 보강판) · 읽는 데 약 30분
선수: 1강(서비스 큰 그림). 이벤트 RSVP 예시가 머릿속에 있으면 좋습니다.
이 강을 마치면: ① HTML·CSS·JavaScript의 역할 분담을 설명한다 ② 정적 vs 동적 화면을 판단한다 ③ SPA와 MPA를 구분한다 ④ React·Vue·Next.js를 왜 쓰는지 설명한다 ⑤ 렌더링 모드(CSR·SSR·SSG·ISR)를 비교한다.
0. 들어가며
프론트엔드는 사용자가 눈으로 보고 손으로 만지는 모든 것 입니다. 버튼·텍스트·이미지·폼·애니메이션·반응성이 모두 프론트엔드의 책임입니다.
이 강은 다음 순서로 갑니다 — ① 화면의 3가지 책임(HTML·CSS·JS) → ② 정적 vs 동적 → ③ SPA vs MPA → ④ 라이브러리·프레임워크 의사결정 → ⑤ 렌더링 모드 4가지 → ⑥ 빌드·패키지 관리 → ⑦ 디자인 시스템 → ⑧ 모바일·반응형.
🎯 러닝 예시 — 이벤트 RSVP의 화면 4개(목록·상세·신청 폼·관리자 대시보드)를 예로 들어, 각 화면의 정적/동적 여부·렌더링 모드·디자인 시스템을 판단 해 봅니다. (직접 만드는 실습이 아니라, 판단 근거를 읽는 용도입니다.)
1. 화면을 이루는 세 계층
1.1 HTML·CSS·JavaScript의 역할 분담
사용자가 보는 화면은 보통 세 계층 으로 이뤄집니다.

| 계층 |
정체 |
책임 |
깨졌을 때 |
| HTML |
구조 계층(마크업) |
요소의 순서·계층·의미를 정의 |
스크린 리더가 읽을 수 없고, 검색 엔진이 색인하지 못함 |
| CSS |
표현 계층(스타일) |
색상·크기·위치·폰트·애니메이션을 지정 |
기획자가 의도한 디자인이 표현되지 않음 |
| JavaScript |
행동 계층(상호작용) |
클릭·입력·스크롤 등 사용자 행동에 반응 |
버튼이 안 눌리고, 폼 검증·동적 효과가 없음 |
1.2 예시 화면 — 이벤트 목록 페이지로 보는 분담
카드 형태로 이벤트를 보여주는 이벤트 목록 페이지 를 예로 들면, 세 계층이 이렇게 나눠 일합니다.

- HTML — 카드들을 목록으로 정의하고, 각 카드 안에 상태 배지·제목·날짜·장소·참여자 수 순서를 지정하고, "신청하기" 버튼 요소를 놓습니다.
- CSS — 카드 너비·그림자·둥근 모서리, 제목/날짜의 색·크기, 상태 배지(모집중/마감) 색, 버튼의 색과 호버 효과, 그리고 반응형(폰 1열 → 태블릿 2열 → PC 3열)을 지정합니다.
- JavaScript — "신청하기"를 누르면 서버에 반영하고 참여자 수를 +1로 갱신하고, 버튼을 "신청 취소"로 바꾸고, "신청되었습니다" 알림을 잠시 띄우며, 마감된 카드는 버튼을 비활성화합니다.
1.3 계층 분담이 깨질 때의 위험
- "CSS로 빠르게" 하려고 HTML 구조를 무시 하면 → 스크린 리더 사용자가 화면을 이용하지 못하고, 검색 엔진이 의미를 파악하지 못하며, 유지보수가 어려워집니다.
- "JavaScript만으로 다 그리면 유연하니까" 하고 HTML·CSS를 무시하면 → JS가 로드되는 동안 사용자가 백지 화면 을 보게 됩니다(느린 네트워크에서 특히 심각).
💡 포인트 — 세 계층을 의도에 맞게 분담하면 빠르고·접근 가능하고·유지보수하기 쉬운 화면이 됩니다. 기획자가 "이 버튼 누르면 이렇게"라고 말하는 대부분은 JavaScript의 영역 입니다.
2. 화면이 만들어지는 두 갈래 — 정적·동적
2.1 정적 페이지(Static Page)
서버가 처음부터 완성된 HTML 을 보냅니다. 누가 열든 같은 내용을 봅니다.
- 장점: 로드 빠름(HTML 한 번), 서버 비용 저렴, SEO 유리(완성 HTML이 이미 존재).
- 한계: 동적 효과가 제한적(JS로 일부만).
- 적합: 회사 소개·블로그 게시물·FAQ·정책/약관 등 거의 안 바뀌는 화면.
2.2 동적 페이지(Dynamic Page)
서버가 틀만 주고, 브라우저(또는 서버)가 데이터를 받아 화면을 그립니다. 사용자·시간에 따라 내용이 바뀝니다.
- 장점: 사용자마다 다른 내용, 실시간 반영 가능.
- 한계: 초기에 백지 화면이 날 수 있고, 서버·네트워크 비용이 추가됩니다.
- 적합: 받은편지함·소셜 타임라인·장바구니·대시보드·개인화 추천처럼 수시로 바뀌는 화면.

2.3 이벤트 RSVP의 정적·동적 판단
| 화면 |
정적/동적 |
이유 |
| 회사·이벤트 상세 정보 |
정적 |
한번 만들면 자주 안 바뀜, SEO 중요 |
| 이벤트 목록 |
동적 |
새 이벤트 추가·종료 시 목록이 변함 |
| 신청 폼 |
동적 |
사용자 입력에 실시간 반응·검증 필요 |
| 관리자 대시보드 |
동적 |
참여자 수·상태가 실시간으로 변함 |
| 개인 신청 내역 |
동적 |
사용자마다 다름, 취소 시 변함 |
3. 한 페이지냐 여러 페이지냐 — SPA vs MPA
프레임워크를 고르기 전에, 화면을 어떻게 넘길지 의 두 갈래를 알아야 합니다. 이것이 뒤의 도구·렌더링 선택에도 영향을 줍니다.

- MPA(Multi-Page Application, 여러 페이지) — 전통적 방식입니다. 링크를 누르면 서버에서 새 HTML 전체 를 받아 화면을 새로고침합니다. 페이지마다 별도 주소·별도 문서죠. 구조가 단순하고 SEO에 유리하지만, 이동할 때마다 깜빡임 이 있고 서버가 매번 HTML을 만듭니다.
- SPA(Single-Page Application, 한 페이지) — 첫 로드로 앱 껍데기 를 받은 뒤, 이후 이동은 JavaScript가 필요한 부분만 갈아끼웁니다(새로고침 없음). 앱처럼 매끄럽고 서버 부하가 낮지만, 첫 로드가 무거울 수 있고 SEO는 별도 대비가 필요합니다. Gmail·구글지도처럼 앱 같은 웹 이 대표적입니다.
비교하면 — 첫 로드 는 MPA가 가볍고, 전환 경험 은 SPA가 매끄럽고, SEO 는 MPA가 유리(SPA는 대비 필요)합니다.
💡 포인트 — SPA/MPA는 페이지를 넘기는 방식, 다음다음 절의 렌더링 모드(CSR/SSR/SSG)는 HTML을 그리는 시점 입니다. 둘은 짝을 이룹니다 — 보통 SPA는 CSR 과, MPA는 서버 렌더(SSR/SSG) 와 함께 갑니다. 그래서 "SPA로 만들되 SEO가 필요한 페이지는 SSR을 섞는" 조합이 나오고, 이를 메타프레임워크(Next.js 등) 가 해줍니다.
4. 라이브러리·프레임워크 의사결정
4.1 도구는 '그때그때의 문제'를 풀며 진화했다

- 1단계 — JavaScript로 DOM 조작이 복잡했다 → jQuery(2006) 가 간단한 셀렉터·조작 문법으로 해결.
- 2단계 — jQuery로도 대규모 앱은 코드가 산란했다 → 컴포넌트 기반 라이브러리 등장: React(2013, Meta) 상태 기반 UI, Vue(2014) 한 파일에 HTML·CSS·JS, Svelte(2019) 컴파일 타임 최적화.
📄 Vue의 '한 파일' 모습 — 위 React와 같은 카드를 Vue의 단일 파일 컴포넌트(SFC)로 쓰면, 화면·동작·스타일이 한 .vue 파일에 모입니다.
vue
<!-- EventCard.vue — 세 구역이 한 파일에 -->
<template> <!-- ① 화면(HTML) -->
<div class="card">
<p>참여자 {{ count }}명</p>
<button @click="count++">신청하기</button>
</div>
</template>
<script setup> // ② 동작(JS)
import { ref } from 'vue'
const count = ref(37) // 바뀌면 화면이 자동 갱신되는 값
</script>
<style scoped> /* ③ 스타일(CSS) — 이 컴포넌트에만 적용 */
.card { border-radius: 12px; }
</style>
- 3단계 — 프레임워크만으론 서버·라우팅·배포 가 별개였다 → 메타프레임워크: Next.js(React), Nuxt(Vue), SvelteKit(Svelte), Remix(로더·액션 중심).
여기서 컴포넌트(재사용 가능한 UI 조각: Button·Card·Modal)와 상태(state)(화면이 기억하는 값)라는 두 기둥이 핵심입니다. 현대 프레임워크의 원리는 "상태가 바뀌면 관련 화면이 자동으로 다시 그려진다" 는 것입니다 — 개발자가 화면을 직접 고쳐 그리지 않고 상태만 바꾸면 됩니다.


실제 코드로는 이렇게 짧습니다. 아래는 React의 함수형 컴포넌트 로, "신청하기" 버튼을 누르면 상태(참여자 수)만 1 늘리고, 화면은 React가 알아서 다시 그립니다.
// EventCard.jsx — 이벤트 카드 하나를 그리는 컴포넌트
function EventCard() {
// count = 화면이 기억하는 값(state). setCount로 바꾸면 화면이 자동 갱신됩니다.
const [count, setCount] = useState(37); // 처음 참여자 수 37
return (
<div className="card">
<h3>사내 해커톤 2026</h3>
<p>참여자 {count}명</p>
{/* 버튼을 누르면 count를 +1 → 화면의 숫자도 자동으로 38로 바뀜 */}
<button onClick={() => setCount(count + 1)}>신청하기</button>
</div>
);
}
4.2 언제 무엇을 — 의사결정 표
| 상황 |
도구 |
이유 |
| 간단한 페이지(FAQ·블로그·정책) |
HTML + CSS만 |
라이브러리 불필요, 빠르고 저렴 |
| 레거시 사이트에 일부 상호작용 추가 |
jQuery |
기존 코드와 호환, 학습곡선 낮음 |
| 중소 규모(초기 MVP) |
React 또는 Vue |
생태계 풍부, 개발 속도 빠름 |
| SEO가 중요한 기업 서비스 |
Next.js |
SSR·SSG 지원, 검색 최적화 |
| 전사 대규모 애플리케이션 |
Next.js + TypeScript |
타입 안정성, 팀 협업 용이 |
| 가벼운 인터랙티브 사이트 |
Svelte |
번들 크기 최소, 성능 우수 |
| 실시간 협업 도구(Figma류) |
React + 정교한 상태 관리 |
복잡한 UI 상태 관리 필요 |
4.3 이벤트 RSVP의 선택 — Next.js + React + TypeScript
정적 페이지(회사 소개)와 동적 페이지(신청)를 모두 지원해야 하므로 SSR·SSG가 필요하고, 신청 폼의 실시간 검증에는 React의 상태 관리가, 관리자 대시보드의 복잡한 상태에는 TypeScript의 타입 정확성이, SNS 공유용 동적 메타 태그에는 SSR이 맞습니다.
🔤 TypeScript가 잡아 주는 것 — TypeScript는 JavaScript에 타입(자료형) 을 붙여, 잘못된 데이터를 코드를 실행하기 전에 미리 잡아 줍니다. 예를 들어 RSVP 신청 데이터의 모양을 interface로 정해 두면:
```typescript
// RSVP 신청 한 건의 '모양'을 정의
interface Rsvp {
userId: number; // 숫자여야 함
name: string; // 문자열이어야 함
status: "attending" | "not_attending"; // 이 둘 중 하나만 허용
}
const r: Rsvp = { userId: 456, name: "김철수", status: "가는중" };
// ↑ 오타! "가는중"은 허용값이 아니라 여기서 바로 오류 표시
```
5. 렌더링 모드 4가지 — 언제 무엇을
화면이 그려지는 시점 에 따라 네 가지 모드가 있습니다. (SPA/MPA가 '페이지를 넘기는 방식'이라면, 렌더링 모드는 '한 화면의 HTML을 언제·어디서 만드나'입니다.)

- CSR(Client Side Rendering) — 서버는 빈 HTML 을 주고 브라우저의 JS가 데이터를 받아 그립니다. 한 번 로드되면 페이지 전환이 빠르고(SPA) 서버 부하가 낮지만, 초기 로드가 느리고 SEO가 약합니다. 적합: SNS 타임라인·지도·Gmail·Slack처럼 로그인 필수·매우 동적인 화면.
- SSR(Server Side Rendering) — 요청마다 서버가 완성 HTML을 그려 보냅니다. 즉시 화면이 뜨고 SEO가 우수하지만, 서버 비용·부하가 큽니다. 이후 JS가 붙어 상호작용이 가능해지는 과정을 하이드레이션 이라 합니다. 적합: 블로그·상품 페이지·뉴스처럼 콘텐츠·SEO가 중요한 화면.
- SSG(Static Site Generation) — 빌드할 때 미리 HTML을 만들어 CDN에서 그대로 서빙합니다. 가장 빠르고 저렴하며 SEO 최고 지만, 콘텐츠가 바뀌면 재빌드·재배포가 필요하고 동적 데이터를 못 담습니다. 적합: 회사 소개·문서·포트폴리오·약관.
- ISR(Incremental Static Regeneration) — 대부분 SSG처럼 빠르게 주되, 일부 페이지를 주기·요청 기준으로 백그라운드에서 재생성 합니다. SSG의 속도 + 자동 갱신을 얻는 대신 설정이 복잡하고 갱신 지연을 허용해야 합니다. 적합: 주간 업데이트 블로그, 시간당 갱신 카탈로그·뉴스.
5.1 이벤트 RSVP의 렌더링 전략
| 페이지 |
모드 |
이유 |
| 회사 소개·이벤트 상세 |
SSG(시간당 1회 ISR) |
SEO 중요, 콘텐츠 자주 안 바뀜, 성능 최우선 |
| 이벤트 목록 |
SSR |
새 이벤트·마감 상태가 자주 변함, SEO 필요 |
| 신청 폼·대시보드 |
CSR |
로그인 필수, SEO 불필요, 실시간 상호작용 |
| 개인 신청 내역 |
SSR |
사용자별 맞춤, 새로고침 시 최신 상태 |
💡 포인트 — 실무는 한 서비스 안에서 페이지마다 모드를 고릅니다. "이 화면은 왜 이 모드?"가 기획·개발의 좋은 대화 주제입니다.
6. 빌드와 패키지 관리 — 왜 이 단계가 있나
6.1 개발 코드 ≠ 배포 코드
개발자가 작성한 코드는 사용자 브라우저에 그대로 가지 않습니다. 읽기 좋은 개발 코드(상세한 이름·주석·디버그 로그)를, 가볍고 안전하고 호환되게 바꾸는 빌드 과정을 거칩니다.

빌드의 목표는 세 가지입니다 — 빠른 로드(파일 크기 축소), 보안(소스 난독화), 호환성(최신 문법을 구형 브라우저용으로).
6.2 패키지 관리자 (npm · pnpm · yarn)
프로젝트가 쓰는 라이브러리 목록 을 관리합니다.
- npm — 가장 널리 쓰이는 기본 표준.
package.json에 의존성, package-lock.json으로 버전 고정.
package.json은 이렇게 생겼습니다 — 이 프로젝트가 어떤 라이브러리를 쓰고(dependencies), 어떤 명령을 갖는지(scripts)를 적어 둔 목록입니다.
{
"name": "rsvp-app",
"scripts": {
"dev": "next dev", // npm run dev → 개발 서버 실행
"build": "next build", // npm run build → 배포용 빌드
"lint": "eslint ." // npm run lint → 코드 검사
},
"dependencies": { // 서비스 실행에 꼭 필요한 라이브러리들
"next": "^15.0.0",
"react": "^19.0.0"
}
}
- yarn — Meta가 만든 것으로 설치가 빠르고 오프라인 캐싱·병렬 설치를 지원.
- pnpm — 최신. 하드 링크로 디스크를 아끼고 속도가 가장 빠릅니다.
선택 기준: npm으로 시작하고, 프로젝트가 커지면 pnpm을 검토합니다.
6.3 빌드 도구 (webpack · Vite · esbuild · Turbopack)
| 도구 |
특징 |
속도 |
학습곡선 |
| webpack |
가장 강력, 설정 복잡 |
느림 |
높음 |
| Vite |
개발 경험 최고, 번들 가벼움 |
매우 빠름 |
낮음 |
| esbuild |
Rust 기반, 번들 속도 최고 |
최고 |
중간 |
| Turbopack |
Rust 기반, webpack 호환 |
최고 |
낮음 |
현재 추천: 일반은 Vite, 풀스택은 Next.js(내장 빌드).
6.4 빌드가 하는 네 가지 일
- ① 트랜스파일링 — 최신 JavaScript(예: ES2024)를 구형 브라우저도 이해하는 문법으로 변환.
- ② 번들링 — 수십~수백 개 파일을 소수(main·vendor·styles)로 묶어 네트워크 요청을 줄임.
- ③ 최소화(Minify) — 공백·주석·긴 변수명을 제거해 크기를 크게 줄임(예: 100KB → 30KB).
- ④ 트리셰이킹 — 실제로 쓰지 않는 코드 를 자동 제거(라이브러리에서 함수 하나만 쓰면 나머지는 빠짐).
💡 비유 — 책 출판과 같습니다. 원고 작성(개발 코드) → 편집·교정(최소화로 군더더기 제거) → 인쇄 최적화(번들·트리셰이킹) → 서점 배포(CDN에 올려 사용자 접근).
7. 디자인 시스템과 UI 컴포넌트
7.1 왜 필요한가
디자인 시스템이 없으면 — 개발자마다 다른 파란색을 쓰고, 같은 버튼이 세 가지 크기로 존재하고, "예상한 디자인과 다르다"는 갈등이 반복되고, 매번 스타일을 새로 작성해 시간을 낭비합니다. 있으면 — 컬러·버튼 패턴이 통일되고, 디자이너·개발자 사이 기준이 명확해지며, 컴포넌트를 재사용해 빠르게 개발합니다.
7.2 디자인 시스템의 3계층

- 레벨 1 — 디자인 토큰(가장 기본): 색상(Primary Blue 등)·타이포그래피(제목/본문 크기)·간격(4·8·16·24px…) 같은 값.
- 레벨 2 — 컴포넌트(토큰으로 만든 재사용 단위): Button·Card·Input.
- 레벨 3 — 패턴(컴포넌트로 만든 화면 부분): Header(로고+내비+버튼), Form(입력+라벨+검증+제출), Modal.
7.3 인기 도구
| 도구 |
특징 |
잘 맞는 규모 |
| Tailwind CSS |
유틸리티 클래스(색·크기를 HTML에 직접) |
빠른 프로토타이핑 |
| Material UI(MUI) |
구글 Material Design 구현, 컴포넌트 풍부 |
대규모 엔터프라이즈 |
| shadcn/ui |
Headless(스타일 최소), 복사해서 수정 |
맞춤 커스터마이즈 |
| Ant Design |
대시보드·관리 화면 컴포넌트 풍부 |
데이터 중심 앱 |
| CSS-in-JS(Styled Components·Emotion) |
JS로 CSS 작성 |
동적 스타일 필요 시 |
💡 비유 — 사내 PPT 마스터 슬라이드> 🎨 Tailwind 맛보기 — "유틸리티 클래스"란 색·여백·크기를 HTML 클래스로 직접 붙이는 방식입니다. 별도 CSS 파일 없이 클래스 이름만으로 스타일이 완성됩니다.
html
<!-- bg-blue-600=파란 배경, text-white=흰 글씨, rounded-lg=둥근 모서리, px-4 py-2=안쪽 여백 -->
<button class="bg-blue-600 text-white rounded-lg px-4 py-2 hover:bg-blue-700">
신청하기
</button>
— 마스터가 없으면 슬라이드마다 폰트·색을 새로 지정하며 일관성이 깨집니다. 마스터가 있으면 발표자는 콘텐츠만 채우고도 프로 같은 결과를 얻습니다. 디자인 시스템이 프론트엔드의 '마스터 슬라이드'입니다.
이벤트 RSVP의 선택: Tailwind CSS + shadcn/ui — 빠른 개발 + 접근성·다크 모드 기본 지원 + Next.js와 호환.
8. 모바일·반응형 의사결정
8.1 네 가지 접근법
- ① 반응형 웹 — 하나의 HTML·CSS로 모든 기기에 대응(CSS 미디어 쿼리). 관리 쉽고 배포 1회 지만, 모든 기기를 만족시키려다 타협이 생기고 큰 화면용 코드까지 내려받습니다.

실제로는 미디어 쿼리 로 "화면이 이만큼 넓어지면 이렇게 배치하라"를 지정합니다. 아래는 폰(1열) → 태블릿(2열) → PC(3열)를 정의한 CSS입니다.
```css
/ 기본(폰): 카드를 1열로 /
.events { display: grid; grid-template-columns: 1fr; }
/ 화면 폭이 768px 이상(태블릿)이면 2열로 /
@media (min-width: 768px) {
.events { grid-template-columns: 1fr 1fr; }
}
/ 1024px 이상(PC)이면 3열로 /
@media (min-width: 1024px) {
.events { grid-template-columns: 1fr 1fr 1fr; }
}
```
- ② PWA(Progressive Web App) — 웹으로 만들되 앱처럼 설치·오프라인·푸시 가 가능. 앱스토어가 불필요 하지만 iOS 지원이 제한적이고 사용자 발견이 어렵습니다.
- ③ 네이티브 앱(iOS/Android) — Swift·Kotlin으로 각각 개발. 최고 성능·기능·앱스토어 노출 이지만 개발 비용이 2배 이고 심사·버전 관리가 복잡합니다.
- ④ React Native / Flutter — 한 번 작성해 iOS·Android 모두 배포. 코드 대부분을 재사용 해 비용을 아끼지만(네이티브를 두 벌 만드는 것보다 훨씬 적음), 성능이 네이티브보다 낮고 복잡한 UI에선 네이티브 코드가 필요합니다.
8.2 결정의 큰 줄기
모바일이 필수가 아니면 반응형 웹으로 충분합니다. 모바일이 필수 라면 — 오프라인·푸시가 필요한지, iOS를 반드시 지원해야 하는지, 예산이 얼마인지에 따라 갈립니다. 예산이 빠듯하면 반응형 웹 또는 React Native, 성능·기능이 최우선이면 네이티브 앱 쪽입니다.
이벤트 RSVP의 선택: 반응형 웹(추후 PWA 고려) — 사내·동호회 이벤트라 모바일은 필수지만 오프라인은 불필요하고, 신청 폼이 단순해 비용·시간 제약이 크기 때문입니다. 폰/태블릿/PC 3단계 반응형으로 정의합니다.
9. 핵심 용어 (40)
| # |
용어 |
정의 |
예시 |
| 1 |
DOM |
브라우저가 HTML을 메모리에 표현한 트리 구조 |
document.querySelector('.card') |
| 2 |
하이드레이션 |
서버가 보낸 정적 HTML에 JS 상호작용을 입히는 과정 |
SSR 후 브라우저에서 React가 수행 |
| 3 |
SPA / MPA |
한 페이지에서 부분 교체 / 페이지마다 새 문서 |
Gmail(SPA) / 전통 웹사이트(MPA) |
| 4 |
번들 |
여러 JS·CSS를 하나로 묶은 것 |
webpack이 100개→3개 파일로 |
| 5 |
트랜스파일 |
최신 JS를 구형 JS로 변환 |
ES2024 → ES5 |
| 6 |
트리셰이킹 |
사용하지 않는 코드 자동 제거 |
함수 1개만 쓰면 나머지는 빠짐 |
| 7 |
컴포넌트 |
재사용 가능한 UI 단위 |
Button·Card·Modal |
| 8 |
props |
부모→자식으로 넘기는 데이터·설정 |
<Button color="blue" /> |
| 9 |
state |
컴포넌트 내부의 변경 가능한 값. 바뀌면 화면이 자동 갱신 |
폼 입력 값 |
| 10 |
라이프사이클 |
컴포넌트의 생성·갱신·제거 단계 |
React useEffect |
| 11 |
Context API |
깊은 계층까지 데이터 전달 |
테마·언어·인증 공유 |
| 12 |
Redux |
전역 상태 관리 라이브러리 |
복잡한 상태를 중앙 관리 |
| 13 |
Virtual DOM |
메모리 상의 가상 DOM |
실제 DOM과 비교해 필요한 부분만 갱신 |
| 14 |
렌더링 |
데이터를 화면에 그리기 |
CSR/SSR/SSG 모두 포함 |
| 15 |
메타 태그 |
<head>의 페이지 정보 |
<meta name="description"> |
| 16 |
SEO |
검색 엔진 최적화 |
검색 상위 노출 |
| 17 |
OG 태그 |
SNS 공유 시 썸네일·제목·설명 |
카카오톡·페이스북 미리보기 |
| 18 |
크로스 브라우징 |
여러 브라우저에서 정상 작동 |
Safari·Chrome 모두 확인 |
| 19 |
WebGL |
브라우저 3D 그래픽 |
Three.js |
| 20 |
Canvas |
픽셀 단위 그리기 API |
이미지 처리·게임 |
| 21 |
SVG |
벡터 그래픽 형식 |
아이콘·로고(확대해도 선명) |
| 22 |
접근성 |
장애인·저시력·청각장애도 사용 가능 |
스크린 리더·alt 텍스트 |
| 23 |
ARIA |
접근성 속성 |
role="button" |
| 24 |
WebFont |
다운로드하는 폰트 |
Noto Sans KR |
| 25 |
Core Web Vitals |
체감 성능 지표(LCP·INP·CLS) |
구글이 검색에 반영(2024.03 FID→INP 대체) |
| 26 |
캐싱 |
자주 쓰는 데이터·파일 저장 |
브라우저·CDN 캐시 |
| 27 |
CDN |
전 세계 분산 서버 |
Cloudflare·CloudFront |
| 28 |
HTTP 캐시 헤더 |
저장 기간 지정 |
Cache-Control: max-age=3600 |
| 29 |
쿠키 |
브라우저의 작은 텍스트 데이터 |
로그인 세션 |
| 30 |
로컬스토리지 |
브라우저 저장소(쿠키보다 큼·영구) |
최근 검색어·테마 |
| 31 |
API |
프론트-백 통신 규약 |
GET /api/events |
| 32 |
REST API |
자원 기반 API 설계 |
표준 형식 |
| 33 |
GraphQL |
쿼리 기반 API |
필요한 필드만 요청 |
| 34 |
타입스크립트 |
JS + 타입 시스템 |
const n: number = 10 |
| 35 |
린트 |
코드 스타일 자동 검사 |
ESLint |
| 36 |
포맷팅 |
코드 자동 정렬 |
Prettier |
| 37 |
테스트 |
의도대로 작동하는지 확인 |
Jest·Cypress |
| 38 |
스토리북 |
컴포넌트 개발·문서화 환경 |
상태별 문서화 |
| 39 |
배포 |
개발 코드를 사용자 환경에 올리기 |
Vercel·Netlify |
| 40 |
다크 모드 |
야간 모드 |
prefers-color-scheme: dark |
10. 한눈에 정리
- 화면 = HTML(구조)·CSS(표현)·JavaScript(행동) 세 계층의 분담.
- 정적/동적 은 '내용이 고정이냐 변하냐', SPA/MPA 는 '페이지를 어떻게 넘기냐', 렌더링 모드(CSR/SSR/SSG/ISR) 는 'HTML을 언제·어디서 그리냐' — 세 축을 조합해 화면을 설계한다.
- 프레임워크는 문제를 풀며 진화(jQuery→React/Vue→메타프레임워크). 두 기둥은 컴포넌트 + 상태.
- 빌드 는 개발 코드를 가볍고 안전하게(트랜스파일·번들·최소화·트리셰이킹) 만들어 CDN으로.
- 디자인 시스템(토큰→컴포넌트→패턴)으로 일관성·속도를 얻고, 모바일 전략(반응형/PWA/네이티브/RN)은 필수·예산으로 고른다.
다음 강 예고
입문(기술 기초) 3강. 백엔드 — 화면 뒤에서 데이터를 지키는 서버. 요청-응답, API·인증·인가, 데이터 검증과 확장성을 봅니다.
※ 원문(선수 M2)을 구성·내용 보존 원칙으로 재구성하고, 다이어그램을 보강(3계층·예시 화면·SPA/MPA·프레임워크 진화·렌더링 4모드·빌드·디자인시스템)했습니다. 프레임워크·지표명은 시점에 따라 세부가 바뀔 수 있습니다.
1부 · 기술 기초
입문(기술 기초) 3강. 백엔드
유형: 이론 (다이어그램 보강판) · 읽는 데 약 30분
선수: 2강(프론트엔드). 이벤트 RSVP 예시가 머릿속에 있으면 좋습니다.
이 강을 마치면: ① 백엔드의 다섯 가지 책임을 설명한다 ② API·인증·인가·비즈니스 로직을 이해한다 ③ 트랜잭션·캐싱·CI/CD 같은 운영 개념을 잡는다.
0. 들어가며
프론트엔드가 화면을 그리는 동안, 백엔드는 데이터를 보호하고 서비스의 규칙을 강제 합니다. 이 강은 하나의 질문을 따라갑니다 — "사용자가 '참석하기'를 누르면, 화면 뒤에서 정확히 무슨 일이 벌어지는가?" 이 질문을 좇다 보면 API·인증·비즈니스 로직·배포까지 자연스럽게 만납니다.
1. 백엔드가 하는 다섯 가지 일

① 데이터 저장·조회(영구 보관) — 가장 기본입니다. 프론트엔드는 화면에만 데이터를 띄우고, 새로고침하면 사라집니다. 백엔드는 이를 데이터베이스(DB) 에 저장해 나중에도 꺼낼 수 있게 합니다. 예를 들어 사용자 A가 "참석"을 누르면 (이벤트123, 사용자456, 상태=참석) 을 저장하고, 하루 뒤 누군가 "누가 왔나?"를 물으면 그 기록을 꺼내 응답합니다. 이 저장·조회의 네 동작이 CRUD(Create·Read·Update·Delete)입니다.
② 인증·권한 — 데이터에는 소유권이 있습니다. 내 신청을 남이 삭제하지 못하게 막는 일이죠. 인증 은 "너 정말 본인이야?"(로그인)이고, 인가 는 "그럼 이걸 할 수 있어?"(권한)입니다.
③ 비즈니스 로직(서비스의 규칙) — "정원은 50명까지", "마감 시간 뒤엔 안 받음", "중복 신청 금지" 같은 규칙입니다. 프론트엔드가 대신할 수 없는 판단으로, 반드시 백엔드가 강제해야 합니다.
④ 외부 통합 — 결제 게이트웨이, 이메일(확인 메일), SMS(인증 문자), 푸시 알림, 분석 서비스 등 외부 시스템과의 대화 입니다. 예: "참석" 신청 시 이메일 서비스를 호출해 확인 메일을 보내고, 이벤트 하루 전 참석자에게 푸시 알림을 보냅니다. 이때 백엔드는 비밀 API 키 로 외부와 통신합니다.
⑤ 안정성·성능·관측 — "앱이 느려요", "어제는 됐는데 오늘 안 돼요"를 막는 일입니다. 캐싱 으로 속도를 높이고, 부하 분산 으로 트래픽을 견디고, 모니터링 으로 장애를 빨리 발견하고, 로깅 으로 원인을 파악합니다.
💡 기획자 포인트 — "앱이 느려요"라는 불만이 오면, 백엔드팀은 이 다섯 중 어디가 문제인지 찾습니다. 투자 우선순위는 대략 로깅(싸고 효과 큼) → 캐싱 → 모니터링 → 부하 분산(필요할 때만) 순입니다. 이 다섯이 없으면 프로토타입처럼 보여도 '실제 서비스'가 되지 못합니다.
2. API — 프론트와의 약속
2.1 API의 정의와 역할
API(Application Programming Interface) 는 백엔드가 "이런 요청을 받으면 이런 응답을 주겠다" 고 약속한 규칙입니다.

초기 웹은 서버가 HTML을 직접 만들어 보냈지만, 지금은 웹·iOS·Android·데스크톱·외부 서비스가 모두 같은 백엔드 와 통신합니다. 각자 다른 형식으로 데이터를 받으면 혼란스럽겠죠. 그래서 API는 모두가 따르는 하나의 규칙 입니다. 예컨대 누가 GET /api/v1/events/123/rsvp 를 물으면 항상 같은 형식의 JSON을 받습니다.
{
"total": 45,
"attendees": [
{"userId": 456, "name": "김철수", "status": "attending"},
{"userId": 789, "name": "이영희", "status": "attending"}
]
}
이렇게 약속하면 프론트엔드는 이 형식을 처리하는 코드를 한 번만 짜면 되고, 모바일 팀도 외부 개발사도 같은 API를 씁니다.
2.2 REST · GraphQL · WebSocket — 언제 무엇을
| 방식 |
특징 |
언제 쓰나 |
| REST |
HTTP 메서드(GET/POST/PUT/DELETE)+URL로 리소스를 다룸 |
대부분의 웹·모바일 앱. 간단·표준 |
| GraphQL |
클라이언트가 "이 필드만 줘"라고 요청 |
필드가 많고 화면마다 필요 데이터가 다를 때(모바일 데이터 절약) |
| WebSocket |
양방향 실시간 연결 유지 |
채팅·실시간 알림·멀티플레이 게임 |
RSVP 앱은 REST가 기본이지만, "참석자 이름·프로필·코멘트만" 필요하면 GraphQL이 유리합니다.
GraphQL 예시 — REST는 정해진 응답을 통째로 받지만, GraphQL은 "필요한 필드만" 골라 한 번에 요청합니다.
# 요청: 이벤트 제목과 참석자 이름만 콕 집어서
query {
event(id: 123) {
title
rsvps { user { name } }
}
}
// 응답: 요청한 모양 그대로 (군더더기 없음)
{ "data": { "event": {
"title": "사내 해커톤 2026",
"rsvps": [ { "user": { "name": "김철수" } }, { "user": { "name": "이영희" } } ]
} } }
WebSocket 예시 — 실시간 신청 현황처럼 "서버가 먼저 알려줘야" 하는 경우에 씁니다. 한 번 연결하면 양방향으로 계속 메시지가 오갑니다.

// 연결 후 서버가 신청이 들어올 때마다 밀어주는 메시지(JSON)
{ "type": "rsvp_update", "eventId": 123, "count": 37, "remaining": 13 }
웹훅(Webhook) 예시 — 반대로 외부 서비스가 "일이 생겼어요"라고 우리 서버로 먼저 알려주는 방식입니다(예: 결제 완료, 메일 열람). 외부가 정해진 주소로 아래 같은 데이터를 보내면, 우리 서버가 받아서 처리합니다.
// 외부(결제사)가 우리 서버의 웹훅 주소로 POST 하는 알림
{ "event": "payment.succeeded", "eventId": 123, "userId": 456, "amount": 0, "at": "2026-10-20T09:14:00Z" }
2.3 CRUD 네 동작
| 동작 |
뜻 |
HTTP |
예시 |
| Create |
생성 |
POST |
/events/123/rsvp 본문 {status:'attending'} |
| Read |
조회 |
GET |
/events/123/rsvp?user_id=456 |
| Update |
수정 |
PUT/PATCH |
/events/123/rsvp/456 본문 {status:'not_attending'} |
| Delete |
삭제 |
DELETE |
/events/123/rsvp/456 |
실제 요청과 응답은 이렇게 오갑니다. 아래는 RSVP 참석 신청을 보내는 REST 요청(위)과 서버가 돌려주는 JSON 응답(아래)입니다. 사람이 그대로 읽을 수 있는 형식이라, 기획자도 "무엇을 보내고 무엇을 받는지"를 눈으로 확인할 수 있습니다.
POST /api/v1/events/123/rsvp # 123번 이벤트에 신청
Authorization: Bearer eyJhbGci... # 로그인 증명(JWT)
Content-Type: application/json
{ "name": "김철수", "email": "chulsoo@company.com", "status": "attending" }
// 201 Created — 신청 성공, 서버가 만든 결과를 돌려줌
{
"rsvpId": 8821,
"eventId": 123,
"status": "attending",
"position": 37, // 37번째 신청자
"remaining": 13, // 남은 자리
"createdAt": "2026-10-20T09:14:00Z"
}
정원이 찼다면 같은 요청에 다른 상태 코드로 답합니다 — 예: 409 Conflict(정원 초과·중복 신청), 400 Bad Request(마감). 이처럼 상태 코드로 성공/실패의 종류를 구분합니다.
기획자가 알아 두면 좋은 자주 쓰는 HTTP 상태 코드 는 이 정도입니다 — 앞자리(2·4·5)만 봐도 성공/요청 실수/서버 문제를 구분할 수 있습니다.
| 코드 |
뜻 |
RSVP 예시 |
| 200 OK |
성공(조회 등) |
참석자 목록 조회 성공 |
| 201 Created |
생성 성공 |
신청이 새로 등록됨 |
| 400 Bad Request |
요청이 잘못됨 |
마감된 이벤트에 신청 |
| 401 Unauthorized |
로그인 안 됨 |
토큰 없이 신청 시도 |
| 403 Forbidden |
권한 없음 |
남의 신청을 삭제 시도 |
| 404 Not Found |
대상 없음 |
없는 이벤트 번호 조회 |
| 409 Conflict |
충돌 |
정원 초과·중복 신청 |
| 500 Server Error |
서버 내부 오류 |
백엔드 버그·DB 장애 |
2.4 API 명세를 함께 보는 법
팀이 함께 보는 API 문서는 Swagger·OpenAPI·Postman 같은 도구로 만듭니다. 명세에는 각 엔드포인트의 요청·응답·에러 케이스 가 담깁니다. 예를 들어 "참석 신청"은 성공 시 {rsvpId, createdAt} 을, 실패 시 409(이미 신청)·400(마감) 을 돌려주도록 약속합니다. 이 명세가 있으면 프론트·백·모바일·외부가 같은 규칙 으로 개발할 수 있습니다.
3. 인증·권한
3.1 인증 vs 인가

- 인증(Authentication) = "넌 누구야?" — 신원 증명. 신분증 확인 에 해당합니다.
- 인가(Authorization) = "그럼 넌 뭘 할 수 있어?" — 권한 확인. 팀 배지 확인("개발팀이니 서버실 출입 가능")에 해당합니다.
3.2 세션 · JWT · OAuth
| 방식 |
저장 위치 |
장점 |
단점 |
언제 |
| 세션 |
서버(메모리/DB) |
간단, 로그아웃 즉시 반영 |
서버 부하, 분산 환경 복잡 |
소규모, 즉시 로그아웃 중요 |
| JWT |
클라이언트(토큰) |
무상태, 분산 쉬움 |
즉시 무효화 까다로움 |
API·모바일·마이크로서비스 |
| OAuth |
제3사(구글·카카오) |
인증 로직 아웃소싱 |
외부 의존 |
소셜 로그인·외부 연동 |
RSVP 규모라면 JWT 가 적당합니다 — 토큰 하나로 "이 사용자가 맞다"를 매 요청에서 빠르게 증명합니다.

토큰이 실제로 어떻게 생겼는지 한 번 뜯어보면 이해가 빠릅니다. JWT는 점(.)으로 나뉜 세 조각(헤더·내용·서명)을 이어 붙인 문자열입니다.

# 실제 토큰(줄바꿈 없이 한 줄) — 세 조각이 점으로 이어져 있습니다
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0NTYiLCJyb2xlIjoiaG9zdCJ9.Zx8kQp3rT9v0aB...
앞 두 조각을 Base64로 풀면(디코딩) 아래처럼 사람이 읽을 수 있는 JSON이 나옵니다. RSVP라면 "이 사용자는 456번, 역할은 이벤트 호스트, 이 토큰은 언제까지 유효" 같은 정보가 담깁니다.
// ① 헤더 — 어떤 방식으로 서명했는지
{ "alg": "HS256", "typ": "JWT" }
// ② 내용(payload) — 누구인지·권한·만료 시각(exp는 유닉스 시간)
{ "sub": "456", "name": "김호스트", "role": "host", "exp": 1735689600 }
⚠️ 중요 — ①②는 '암호화'가 아니라 Base64 '인코딩'일 뿐이라 누구나 열어볼 수 있습니다. 비밀번호·주민번호 같은 민감정보를 payload에 넣으면 안 됩니다. 위조를 막는 것은 ③ 서명입니다 — 서버만 아는 비밀키로 만든 서명이라, 내용을 한 글자라도 바꾸면 서명이 안 맞아 거부됩니다. 그래서 서버는 세션을 따로 저장하지 않고도 "우리가 발급한 진짜 토큰"인지 즉시 확인할 수 있습니다(무상태).
소셜 로그인(OAuth)은 흐름이 조금 다릅니다. 사용자의 비밀번호를 우리 앱이 직접 받지 않고, 구글·카카오 같은 외부 인증 서버에 맡긴 뒤 '증표'만 넘겨받습니다.

마지막 토큰 교환 단계에서 우리 앱이 받는 응답은 대략 이렇게 생겼습니다.
// 구글이 발급하는 토큰 응답
{
"access_token": "ya29.a0Af...", // 이 토큰으로 사용자 정보를 조회
"token_type": "Bearer",
"expires_in": 3599, // 초 단위 만료(약 1시간)
"id_token": "eyJhbGci..." // 사용자 신원이 담긴 JWT(OpenID Connect)
}
우리 앱은 비밀번호를 저장하지 않으니 유출 위험이 사라지고, 이후에는 자체 JWT로 세션을 이어갑니다.
3.3 권한 모델 — RBAC · ABAC · RLS
- RBAC(역할 기반) — 역할별 권한. "일반 사용자는 자신의 RSVP만 수정".
- ABAC(속성 기반) — 시간·IP·기기 등 속성 고려. "오후 6시 이후 신청 불가".
- RLS(행 단위 보안) — 데이터베이스가 행 단위 로 강제. "사용자 A는 자신의 RSVP 행만 조회".
RSVP 앱은 RBAC + RLS 조합이 좋습니다 — 역할로 기본 권한을 주고, DB에서 행 단위로 강제합니다.
3.4 RSVP의 권한 매트릭스
| 역할 |
자신 RSVP 수정 |
자신 RSVP 삭제 |
타인 RSVP 삭제 |
참석자 목록 |
통계 |
| 일반 참석자 |
O |
O |
X |
O |
X |
| 이벤트 호스트 |
O |
O |
O |
O |
O |
| 관리자 |
O |
O |
O |
O |
O(전체) |
이런 권한 매트릭스가 있으면, "호스트는 참석자를 삭제할 수 있어야 한다" 같은 요구가 어디에 어떻게 반영되는지 명확해집니다.
4. 비즈니스 로직
4.1 비즈니스 로직이란
서비스가 어떤 규칙으로 동작하는지 를 정의하는 코드입니다("이메일 중복 확인", "배송 전에만 취소", "쿠폰 한 번만"). 이 규칙이 없으면 서비스가 혼란에 빠지며, 반드시 백엔드에 있어야 합니다(프론트엔드는 조작 가능하므로).
4.2 MVC 패턴
초기에는 한 파일에 데이터 저장·화면·규칙이 뒤섞였습니다. MVC(Model–View–Controller) 는 이를 나눕니다 — Model(데이터+규칙), View(응답 화면/JSON), Controller(요청을 받아 Model 호출·응답 조율). 이렇게 나누면 같은 Model을 웹·모바일에서 재사용하고, 규칙을 한 곳만 고치면 되고, 테스트가 쉬워집니다.
4.3 RSVP의 규칙 네 가지 — '참석'이 통과해야 할 관문

- 마감 처리 — 현재 시간이 마감을 지났으면
400("신청이 마감되었습니다").
- 정원 초과 — 참석자 수가 정원 이상이면
409("정원이 가득 찼습니다").
- 중복 신청 — 이미 신청 기록이 있으면
409("이미 신청하셨습니다").
- 종료 후 — 이벤트 종료일이 지났으면 신청·수정·삭제 금지, 조회만 허용.
⚠️ 왜 백엔드여야 하나 — 이 규칙들을 프론트엔드에만 두면, 악의적 사용자가 개발자 도구로 "마감 확인 코드"를 지나칠 수 있습니다. 마감·정원을 진짜로 강제하려면 백엔드가 절대적으로 검증 해야 합니다.
5. 백엔드 언어·프레임워크
5.1 핵심은 같고 문법만 다르다
모든 백엔드 언어가 하는 일은 같습니다 — 요청 받기 → 데이터 검증 → DB 쿼리 → 응답 생성 → 외부 API 호출. 차이는 문법·도구·생태계 이며, 사용자 입장에서 Python이든 Java든 같은 기능 을 합니다. 그래서 중요한 것은 언어 자체보다 개발 속도와 팀의 숙련도 입니다. 예컨대 같은 기능이라도 팀이 익숙한 언어로 만들면 훨씬 빠릅니다.
# Python FastAPI 예시 (흐름만 보세요)
@app.post("/api/v1/events/{eventId}/rsvp")
def create_rsvp(eventId: int, request: RSVPRequest):
if is_event_closed(eventId): # 마감 검증
raise HTTPException(400, "신청 마감")
db.insert("rsvp", ...) # DB 저장
return {"rsvpId": 123, "createdAt": "2026-05-04"}
// Node.js Express 예시 (거의 같은 로직)
app.post("/api/v1/events/:eventId/rsvp", async (req, res) => {
if (isEventClosed(eventId)) return res.status(400).json({error: "신청 마감"});
const rsvp = await db.insert("rsvp", ...);
res.json({rsvpId: rsvp.id, createdAt: rsvp.created_at});
});
5.2 언어별 강점
| 언어 |
강점 |
약점 |
좋은 대상 |
| Python |
빠른 개발·데이터 처리·AI 연계 |
실행 속도 |
스타트업, 데이터 중심 |
| Node.js |
프론트·백 같은 언어, 실시간 |
대규모 CPU 작업 |
풀스택 팀, 실시간 앱 |
| Go |
빠른 속도·동시성·간단한 배포 |
학습곡선 |
고성능 마이크로서비스 |
| Java |
엔터프라이즈 안정성·성능 |
보일러플레이트 많음 |
금융·대규모 시스템 |
| Ruby |
쉬운 문법·완성도 높은 프레임워크 |
속도 |
초기 프로토타입 |
| C# |
MS 생태계·좋은 도구 |
Windows 의존 |
엔터프라이즈·Azure |
RSVP 같은 중소 프로젝트는 Python(FastAPI) 또는 Node.js(NestJS) 로 충분합니다.
5.3 프레임워크가 자동화하는 것
프레임워크 는 반복 작업을 미리 해둔 틀입니다 — 라우팅(URL→함수)·미들웨어(공통 전처리)·ORM(SQL 없이 객체로 DB)·인증·에러 처리·문서 자동 생성. 프레임워크가 없으면 이 모두를 수동으로 만들어야 해서 느리고 버그가 많습니다.
여기서 ORM(SQL 없이 객체로 DB를 다루는 도구)이 무엇인지 잠깐 보면 좋습니다. 아래는 인기 ORM인 Prisma 로 "123번 이벤트의 참석자를 조회"하는 코드입니다 — SQL을 몰라도 메서드 호출 로 DB를 다룹니다.
// SQL 대신 객체·메서드로 조회 (Prisma)
const rsvps = await prisma.rsvp.findMany({
where: { eventId: 123, status: "attending" }, // 123번 이벤트의 '참석' 신청만
include: { user: true }, // 신청자 정보도 함께
});
// 실제로는 아래 SQL로 번역되어 실행됩니다:
// SELECT * FROM rsvps JOIN users ... WHERE event_id = 123 AND status = 'attending';
5.4 장기전 vs 단기전
| 상황 |
선택 |
정당화 |
| 3개월 내 MVP 진출 |
Python/Ruby(빠름) |
속도 > 성능 |
| 1년 유지, 유지자 많음 |
Node.js(생태계 크고 쉬움) |
팀 편의성 |
| 3년+ 대규모·성능 중요 |
Go/Java(안정성) |
성능 > 개발속도 |
이 차이를 알면 "3개월이 현실적인가?"를 함께 판단할 수 있습니다.
6. 컨테이너와 배포 자동화
6.1 Docker — '내 컴퓨터에선 되는데' 문제 해결
Docker 는 앱 + 의존성(라이브러리) + 실행 환경 을 한 상자(이미지)에 담습니다. 개발 환경에선 되는데 운영 환경에선 안 되는 문제를 없애, 어디서든 같은 환경 에서 앱이 돌게 합니다. 이 이미지를 실행한 것이 컨테이너 입니다.
아주 단순한 예로, 아래는 파이썬 백엔드를 컨테이너로 담는 Dockerfile입니다. "어떤 재료(베이스 이미지)를 깔고, 무엇을 복사하고, 어떻게 실행하라"를 적은 조리법이라고 보면 됩니다.
# 1) 파이썬이 설치된 표준 환경에서 시작
FROM python:3.12-slim
# 2) 작업 폴더 지정
WORKDIR /app
# 3) 의존성 목록을 먼저 복사해 설치(캐시 활용)
COPY requirements.txt .
RUN pip install -r requirements.txt
# 4) 나머지 코드 복사
COPY . .
# 5) 이 명령으로 서버를 실행
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
이 파일 하나면 내 노트북·동료 PC·클라우드 어디서든 똑같은 환경으로 실행됩니다.
6.2 모놀리식 vs 마이크로서비스
- 모놀리식 — 모든 기능이 한 덩어리. 개발·배포가 간단하고 트랜잭션이 쉽지만, 한 부분 장애가 전체로 번지고 확장이 어렵습니다. 초기~수백만 사용자 에 적합.
- 마이크로서비스 — 기능별 독립 서비스. 독립 배포·확장이 쉽지만 복잡하고 서비스 간 통신 비용이 큽니다. 대규모·큰 팀 에 적합.
RSVP 앱은 모놀리식으로 시작 하고, 필요할 때 나누면 됩니다.

6.3 CI/CD 파이프라인

가장 널리 쓰는 도구가 GitHub Actions입니다. 저장소에 아래 같은 YAML 파일 하나를 두면, 코드를 push할 때마다 GitHub이 자동으로 검사·빌드를 돌립니다. "언제(on) → 무엇을(steps)"을 적은 조리법입니다.
# .github/workflows/ci.yml
name: CI
on: [push] # push가 일어나면 실행
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # 코드 내려받기
- run: npm install # 의존성 설치
- run: npm run lint # 코드 검사(ESLint)
- run: npm test # 테스트 실행
# 통과하면 이어서 배포 단계(Vercel 등)로 연결
- CI(지속적 통합) — 코드 변경 → 자동 테스트 → 병합.
- CD(지속적 배포) — 테스트 통과 → 자동 배포.
흐름은 커밋·푸시 → ① 린트(문법·스타일) → ② 단위 테스트(함수별) → ③ 통합 테스트(전체 흐름) → ④ 빌드(Docker 이미지) → ⑤ 배포 이고, 어느 단계든 실패하면 자동으로 멈추고 개발자에게 알립니다. 대략 30분 안에 코드가 사용자에게 닿기 때문에, "오늘 이 버그 고쳤어요?"에 "예, 1시간 뒤 반영됩니다"라고 답할 수 있습니다.
7. 성능과 안정성
7.1 캐싱 — Redis·CDN
캐싱 은 자주 쓰는 데이터를 빠른 저장소에 복사 하는 것입니다. Redis(메모리 캐시)에 "현재 참석자 수=45"를 저장해 DB 대신 메모리에서 응답하고, CDN 은 이미지·JS·CSS 같은 정적 파일을 전 세계 엣지 서버에 복사해 사용자 근처에서 빠르게 제공합니다. "참석자 조회"를 100번 받아도, 캐시가 있으면 DB는 한 번만 두드립니다.

7.2 트랜잭션·ACID — 동시 신청의 함정
트랜잭션 은 "여러 작업이 모두 성공하거나 모두 실패" 를 보장합니다. 그 성질이 ACID(원자성·일관성·격리성·지속성)입니다. 왜 필요한지는 동시 신청 에서 드러납니다.

정원 50, 현재 49명일 때 A·B가 동시에 신청하면 — 트랜잭션이 없으면 둘 다 "49"를 읽고 각자 저장해 51명(오버부킹) 이 됩니다. 트랜잭션 + 행 잠금 이 있으면 A가 처리하는 동안 B는 기다렸다가, A가 50을 채운 뒤엔 정원 초과로 거부되어 정확히 50명 이 유지됩니다.
7.3 메시지 큐 — 비동기 처리
메시지 큐 는 무거운 작업을 줄에 넣고 나중에 처리합니다. 이벤트 공지 후 200명이 동시에 신청해도, "신청 저장 → 큐에 '이메일 발송' 추가 → 즉시 응답" 하고 워커가 백그라운드에서 이메일을 보냅니다. 사용자는 기다리지 않습니다(RabbitMQ·Kafka 등).

7.4 부하 분산 — 로드 밸런싱
한 대 서버로는 한계가 있어 여러 대에 나눕니다. 로드 밸런서 가 들어오는 요청을 서버 A·B·C에 고르게 분배하고, 한 대가 죽어도 나머지가 계속 처리합니다.

7.5 모니터링·로깅 — 운영의 안전망
로깅 은 요청·에러·상태를 기록하고(예: 14:23:15 rsvp 409 정원초과), 모니터링 은 CPU·응답 시간·에러율을 실시간으로 보며 임계치를 넘으면 알람을 울립니다(Datadog·Prometheus 등).
💡 기획자 포인트 — 로깅·모니터링이 없으면 원인을 알 수 없어 무조건 큰 해결책(서버 증설)을 택하게 됩니다. 있으면 "CPU 80%, 캐시 부재" 처럼 진단해 가장 싼 처방 을 고를 수 있습니다.
8. 백엔드 투자 우선순위
무엇부터 개선할지의 기준입니다(위에서부터).
| 순위 |
항목 |
징후 |
시기 |
| 1 |
로깅·모니터링 |
"버그가 뭔지·어디가 느린지 모름" |
초기 3개월 |
| 2 |
자동화 테스트 |
"배포마다 QA 2주, 버그 반복" |
초기 6개월 |
| 3 |
캐싱 |
"조회 API가 1초, 느린 응답" |
사용자 5만+ |
| 4 |
API 버전 관리 |
"요청 때마다 기존 API를 바꿔야 함" |
클라이언트 3+ |
| 5 |
마이크로서비스 |
"전체 배포 30분, 한 버그가 전체 다운" |
사용자 100만+ |
9. 자주 나오는 기술 질문
- "이 기능이 백엔드인가, 프론트엔드인가?" — 대개 둘 다 필요하지만, 안전을 위해 백엔드에 꼭 있어야 합니다. 예: "마지막 신청 시각 표시"는 프론트가 화면에 보여주되, 백엔드가 DB에 저장해야 새로고침에도 유지되고 조작을 막습니다.
- "에러 응답 형식은 어디서 정하나?" — API 명세 로 정합니다. 마감 이벤트에 신청 시
400인지 409인지, 본문 형식이 일관적인지 등을 명세에서 약속합니다.
- "테스트는 누가 하나?" — 다층 방어입니다: 백엔드 단위 테스트 → 프론트·백 통합 테스트 → QA 수용 테스트 → 운영 모니터링. 단위 테스트가 없으면 버그가 QA 단계에서야 발견돼 비용이 커집니다.
- "API 버전 관리는 왜?" —
/api/v1/… 을 쓰던 모바일 앱이 있는데 응답을 바꾸면 구버전 앱이 깨집니다. 그래서 /api/v2/… 로 나눠 호환성 을 지킵니다.
10. 핵심 용어
| 용어 |
정의 |
| API / REST / GraphQL / WebSocket |
요청-응답 규칙 / 자원+메서드 / 필요 필드만 / 양방향 실시간 |
| JWT / 세션 / OAuth |
토큰 기반 / 서버 저장 / 외부 위임 인증 |
| 인증 / 인가 |
신원 확인 / 권한 확인 |
| RBAC / ABAC / RLS |
역할 기반 / 속성 기반 / 행 단위 권한 |
| CRUD |
생성·조회·수정·삭제 |
| MVC / ORM / 미들웨어 |
모델-뷰-컨트롤러 / 객체로 DB / 공통 전처리 |
| 트랜잭션 / ACID |
모두 성공·모두 실패 / 원자·일관·격리·지속 |
| 캐싱 / Redis / CDN |
재사용 저장 / 메모리 캐시 / 정적 파일 분산 |
| 메시지 큐 / RabbitMQ |
비동기 작업 큐 |
| Docker / 컨테이너 / CI·CD |
앱 포장 / 격리 실행 / 통합·배포 자동화 |
| 로드 밸런싱 / 모놀리식 / 마이크로서비스 |
요청 분산 / 한 덩어리 / 기능별 분리 |
| 로깅 / 모니터링 |
기록 / 실시간 상태 추적 |
| 인덱스 / 정규화 / n+1 문제 |
검색 가속 / 중복 제거 설계 / 1번 쿼리가 n번 추가 쿼리를 부르는 비효율 |
| 타임아웃 / 롤백 / 핫픽스 |
오래 걸려 끊김 / 이전 버전 복귀 / 긴급 수정 배포 |
11. 한눈에 정리
- 백엔드의 다섯 책임 = 저장·조회 / 인증·권한 / 비즈니스 로직 / 외부 통합 / 안정성·관측.
- API(REST/GraphQL/WebSocket)는 프론트-백의 계약이고, 상호작용은 요청→인증·인가·검증·로직→DB→응답 왕복.
- 규칙(마감·정원·중복·종료)은 반드시 백엔드가 강제. 동시성은 트랜잭션(ACID) 으로.
- 배포는 Docker + CI/CD 로 자동화, 운영은 캐싱·큐·부하분산·로깅·모니터링 으로 지킴.
다음 강 예고
입문(기술 기초) 4강. 데이터·데이터베이스 — 정보를 어떻게 담고 지키나. 관계형 vs NoSQL, 스키마·인덱스·트랜잭션, 그리고 앞서 배운 벡터 DB와의 연결을 봅니다.
※ 원문(선수 M3)을 구성·내용 보존 원칙으로 재구성하고 존댓말로 통일했으며, 다이어그램을 보강(5책임·요청 여정·인증/인가·비즈니스 규칙·트랜잭션·CI/CD)했습니다. 언어·도구·수치는 시점에 따라 달라질 수 있습니다.
1부 · 기술 기초
입문(기술 기초) 4강. 데이터
유형: 이론 (다이어그램 보강판) · 읽는 데 약 30분
선수: 3강(백엔드). 이벤트 RSVP 예시가 머릿속에 있으면 좋습니다.
핵심 물음: "어떤 데이터를 어디에, 어떤 구조로 보관할 것인가?"
0. 들어가며
데이터는 기획 결정을 가장 많이 제약하는 요소입니다. 기능을 추가하거나 구조를 바꾸려 할 때 — "이 정보는 지금 구조로는 저장할 수 없어요", "마이그레이션에 며칠 필요합니다", "권한을 다시 짜야 해서 2주 걸립니다" 같은 말이 계속 나옵니다. 데이터 구조를 대략이라도 이해하면, 설계 단계에서 이런 함정을 피할 수 있습니다.
이 강은 데이터의 네 종류에서 시작해 관계형 DB·NoSQL·객체 스토리지·권한 모델까지 훑고, 각 절을 이벤트 RSVP 사례로 연습합니다.
1. 데이터의 네 종류
어디에 보관할지 정하려면, 먼저 어떤 데이터인지 분류 하는 것이 첫 단계입니다.

- 정형(Structured) — 회원의 이름·이메일, 이벤트의 제목·정원, 결제의 금액처럼 정해진 틀 에 맞는 데이터. 행·열의 표로 정리되고 자료형이 명확하며 검색·집계가 빠릅니다. → 관계형 DB(PostgreSQL·MySQL·SQLite).
- 반정형(Semi-structured) — 서버 로그, 사용자 이벤트 스트림, API 응답 JSON처럼 기본 구조는 있지만 필드가 들쭉날쭉 한 데이터. 구조가 진화해도 기존 데이터가 잘 깨지지 않습니다. → 문서형 NoSQL(MongoDB)·데이터 웨어하우스(BigQuery).
- 비정형(Unstructured) — 이미지·영상·PDF·음성처럼 자유 형식이고 크며 검색이 어려운 데이터. DB에 직접 넣기보다 메타데이터만 DB에, 실제 파일은 분리된 저장소에 둡니다. → 객체 스토리지(S3·GCS·R2).
- 시계열(Time-series) — CPU·트래픽·시세·센서처럼 시간 축에 쌓이는 데이터. 최근 것만 자주 조회하고 저가 저장·빠른 집계가 중요합니다. → 시계열 DB(InfluxDB·Prometheus)·메모리(Redis).
RSVP 예: 정형(회원·이벤트·신청·관리자) · 반정형(이벤트별 커스텀 필드) · 비정형(포스터·증명 PDF) · 시계열(시간당 신청 수·실시간 현황).
2. 관계형 데이터베이스
2.1 테이블·컬럼·행, 그리고 외래키
관계형 DB는 엑셀 시트 여러 개가 서로 연결된 구조 라고 생각하면 쉽습니다.

- 테이블 — 같은 종류의 데이터 묶음(회원·이벤트·신청).
- 컬럼(열) — 각 데이터의 속성(id·email·name).
- 행(Row) — 개별 레코드.
- PK(기본키) — 각 행을 고유 식별(보통 id).
- FK(외래키) — 다른 테이블의 PK를 참조 하는 연결고리.
이 구조를 실제 SQL로 만들면 이렇게 됩니다. events(이벤트)와 rsvps(신청) 두 표를 만들고, rsvps가 events를 가리키는 외래키로 이어집니다.
-- 이벤트 표
CREATE TABLE events (
id SERIAL PRIMARY KEY, -- PK: 이벤트마다 자동 부여되는 고유 번호
title TEXT NOT NULL, -- 제목(빈 값 금지)
capacity INT NOT NULL -- 정원
);
-- 신청 표
CREATE TABLE rsvps (
id SERIAL PRIMARY KEY,
event_id INT REFERENCES events(id), -- FK: 어떤 이벤트의 신청인지 연결
user_id INT NOT NULL, -- 누가 신청했는지
status TEXT DEFAULT 'attending' -- 상태(기본값 '참석')
);
외래키 덕분에 "홍길동이 신청한 모든 이벤트"는 rsvps에서 user_id로 찾아 각 event_id로 events를 JOIN 해 얻고, "이 이벤트에 신청한 사람"은 반대로 조회합니다. 이래서 관계형 이라 부릅니다.

이 "이어 붙이기"를 SQL로 쓰면 JOIN입니다. rsvps의 user_id로 users를 연결해, 신청 기록 + 신청자 이름 을 한 번에 가져옵니다.
-- 123번 이벤트에 신청한 사람의 이름과 상태를 조회
SELECT users.name, rsvps.status -- 원하는 컬럼만
FROM rsvps
JOIN users ON rsvps.user_id = users.id -- 신청.user_id ↔ 회원.id 로 연결
WHERE rsvps.event_id = 123;
결과는 두 표가 합쳐진 하나의 표처럼 나옵니다.
| name |
status |
| 김철수 |
attending |
| 이영희 |
attending |
2.2 정규화 — 같은 정보를 한 번만
같은 정보가 여러 곳에 흩어지면 일관성이 깨집니다. 예를 들어 rsvps에 user_id 뿐 아니라 user_name 까지 저장하면, 이름이 바뀔 때 두 곳을 모두 고쳐야 하고 한 곳만 고치면 불일치가 생깁니다. rsvps에는 user_id 만 두고 필요할 때 JOIN으로 이름을 가져오면 됩니다. 이것이 정규화(Normalization) — 저장 공간을 아끼고 수정 시점을 명확히 합니다. (성능을 위해 일부러 중복을 허용하는 것은 역정규화 입니다.)

2.3 인덱스·트랜잭션·ACID
- 인덱스 — 빠르게 찾기 위한 색인입니다. 10만 명 중 "홍길동"을 찾을 때, 입사년도 인덱스가 있으면 해당 그룹만 좁혀 훨씬 빠릅니다.

인덱스는 SQL 한 줄로 만듭니다. 예를 들어 "특정 이벤트의 신청"을 자주 조회한다면, event_id에 인덱스를 걸어 둡니다.
sql
-- rsvps 표의 event_id 컬럼에 색인 생성 → event_id로 찾는 조회가 빨라짐
CREATE INDEX idx_rsvps_event ON rsvps(event_id);
- 트랜잭션 — 여러 작업을 함께 성공하거나 함께 실패 하게 묶는 단위입니다. "신청 기록 생성 + 신청자 수 증가"를 한 트랜잭션으로 감싸면, 중간에 에러가 나도 둘 다 취소 되어 불일치가 없습니다.
- ACID — 트랜잭션의 네 성질: 원자성(중간 중단 없음)·일관성(규칙 유지, 예: 신청자 수 음수 불가)·격리성(동시 실행이 서로 간섭 안 함)·지속성(저장되면 장애에도 안전). (동시 신청 오버부킹을 막는 원리는 3강에서 봤습니다.)
2.4 PostgreSQL · MySQL · SQLite
| 특성 |
PostgreSQL |
MySQL |
SQLite |
| 복잡한 쿼리 |
우수(JSON·배열·윈도우 함수) |
보통 |
제한적 |
| 동시 사용자 |
수천+ |
수백~수천 |
수십 |
| 권한(RLS) |
지원 |
제한적 |
미지원 |
| 설치·운영 |
자체 관리 |
상대적으로 쉬움 |
파일 기반, 가장 간편 |
| 용도 |
프로덕션 서비스 |
웹 서비스 |
모바일·프로토타입 |
3. NoSQL과 메모리 DB
3.1 NoSQL이란
NoSQL은 "Not Only SQL" — 테이블 구조를 고집하지 않고 더 유연하게 저장하는 방식들 의 통칭입니다.
- 문서형(MongoDB·Firestore) — JSON 문서를 그대로 저장. 문서마다 필드가 달라도 되고 깊은 객체도 바로 담습니다.
- 키-값(Redis·Memcached) — key에 대한 value를 메모리에 저장해 매우 빠릅니다. TTL(시간 제한)을 줄 수 있어 세션·캐시·실시간 순위표에 적합.
- 분산(DynamoDB·Cassandra) — 수십억 행을 여러 서버에 나눠 저장. 확장성이 높고, 일관성보다 가용성 을 택해 가끔 불일치를 허용합니다.
3.2 트레이드오프와 선택
관계형 DB는 정확성(ACID) 을 최우선으로 복잡한 관계를 안전하게 다루지만 확장 시 비용·복잡도가 늘고, NoSQL은 속도·확장성·유연성 을 우선하되 일관성 관리를 개발자가 책임집니다.

| 상황 |
추천 |
| 구조가 명확하고 관계가 많음(회원·주문·결제) |
RDB |
| 필드가 자주 바뀌거나 유연해야 함 |
NoSQL(문서형) |
| 실시간 순위표·세션·캐시 |
NoSQL(키-값·메모리) |
| 수십억 행을 여러 서버에 분산 |
NoSQL(분산형) |
| 확실하지 않음 |
RDB로 시작, 필요하면 확장 |
RSVP 예: 실시간 신청 수·캐싱은 Redis, 이벤트별 커스텀 필드는 MongoDB, 초대형 동시 신청은 DynamoDB.
4. 파일·이미지 보관 — 객체 스토리지
4.1 서버 디스크 대신 객체 스토리지
파일을 서버 디스크 에 저장하면(/uploads/poster.jpg) — 서버가 여러 대면 위치 추적이 필요하고, 서버가 초기화되면 파일이 사라지고, 용량 확장·백업이 어렵습니다. 대신 객체 스토리지(AWS S3 등) 에 두면 모든 파일이 중앙에 있어 여러 서버에서 안전하게 접근하고, 자동 백업·복제·국제 배포(CDN)가 되며, 용량이 자동 확장됩니다. (S3·Google Cloud Storage·Cloudflare R2·자체 호스팅 MinIO 등.)
객체 스토리지는 저장소(Bucket) → 식별자(Key, 경로) → 객체(파일+메타데이터) 의 3층으로 관리합니다.
4.2 권한과 CDN

- 권한 — 퍼블릭(이벤트 포스터: 누구나·CDN 공개), 프라이빗(개인 신청 PDF: 로그인 확인 후 제공), 서명된 URL(제한 시간만 유효한 일회성 링크, 예: 이메일 확인 링크 1시간 후 만료).
- CDN(Content Delivery Network) — 원본(예: 미국 S3)에서 매번 받으면 느리므로, 전 세계 엣지 서버 에 복제해 사용자와 가까운 곳에서 제공합니다. 서울 사용자는 서울 엣지에서 수 ms에 받습니다.
RSVP 예: 포스터는 S3+CDN(공개), 참여자 증명서는 S3(비공개)+서명된 URL, 당일 사진은 S3(비공개, 관리자만).
5. BaaS — 통합 솔루션
BaaS(Backend as a Service) 는 데이터베이스·인증·파일 저장소·API를 한곳에서 제공합니다.
| 플랫폼 |
RDB |
NoSQL |
인증 |
파일 |
RLS |
특징 |
| Firebase |
– |
Firestore |
O |
O |
제한적 |
가장 먼저(2012) 시장을 염, 저가 시작·확장 시 고가 |
| Supabase |
PostgreSQL |
– |
O |
O |
O |
SQL-first, RLS 강력 |
| Appwrite |
– |
MongoDB |
O |
O |
기본 |
자체 호스팅 가능 |
| PocketBase |
SQLite |
– |
O |
O |
O |
무료(자체 호스팅) |
같이(BaaS) 는 인증-DB 연결이 자동이고 API를 직접 짜지 않아 매우 빠르게 출시 하지만, 커질수록 비용·종속·자유도 제약이 있습니다. 따로(PostgreSQL + 자체 API + S3) 는 완전한 통제와 대규모 저비용 을 주지만 초기 비용·팀·보안 책임이 큽니다.
RSVP 예: MVP는 Supabase(PostgreSQL 정규화 + RLS + 이미지 저장 + 빠른 출시), 스케일 후 자체 API로 이전(복잡한 로직·결제·모니터링).
Supabase 같은 BaaS는 프론트엔드 코드에서 바로 DB를 부를 수 있습니다. 아래는 접속을 초기화하고, "참석자 목록"을 한 번에 조회하는 예입니다(SQL을 직접 쓰지 않아도 됩니다).
import { createClient } from '@supabase/supabase-js'
// ① 접속 초기화 — 주소와 공개 키로 연결 (키는 .env에서 불러옴)
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
// ② 123번 이벤트의 '참석' 신청만 조회
const { data, error } = await supabase
.from('rsvps') // rsvps 표에서
.select('user_id, status') // 이 컬럼만
.eq('event_id', 123) // event_id = 123 인 행만
.eq('status', 'attending') // status = '참석' 인 행만
6. 권한 모델 — RLS
6.1 권한이 깨지면
사용자 A가 B의 신청 정보를 조회하거나(프라이버시 위반), 관리자 X가 담당하지 않는 이벤트를 수정하는(무결성 파괴) 일을 권한 누출(Authorization Bug) 이라 하며, 가장 흔한 보안 사고 중 하나입니다.
6.2 코드가 아니라 DB에서 강제 — RLS

권한을 코드에서만 확인하면(if (user.role === "admin")) 브라우저 도구로 값을 위조하거나 로직 버그로 뚫릴 수 있습니다. RLS(Row Level Security, 행 단위 보안) 는 데이터베이스가 각 사용자가 볼 수 있는 행을 강제합니다.
-- 사용자는 자신의 신청만 조회
CREATE POLICY user_own_rsvps ON rsvps
FOR SELECT USING (auth.uid() = user_id);
-- 이벤트 관리자는 담당 이벤트의 신청을 관리
CREATE POLICY admin_manage_rsvps ON rsvps
FOR UPDATE USING (
event_id IN (SELECT event_id FROM admins WHERE user_id = auth.uid())
);
이렇게 하면 코드에 버그가 있어도, 심지어 직접 쿼리해도 권한 위반이 불가능합니다 — 단일 진실 공급원(SSOT). 권한은 컬럼/행/테이블/DB 단위로 걸 수 있는데, RSVP에는 행 단위(RLS) 가 최적입니다("사용자는 본인 행, 관리자는 모든 행"이 DB에서 자동 강제).
7. 데이터의 흐름

사용자가 "신청하기"를 누르면 — ① 화면이 POST /api/rsvps 요청(토큰 포함) → ② API가 토큰·존재·중복 을 검증 → ③ rsvps에 INSERT → ④ RLS가 권한을 자동 확인 → ⑤ 응답({rsvpId, status})을 받아 화면이 "완료"로 갱신하고 버튼을 "취소"로 바꿉니다.
이때 데이터가 거쳐가는 곳은 프론트 메모리(휘발) → HTTP(HTTPS 암호화) → API 서버 메모리(임시) → 데이터베이스(영구·백업) → 응답(캐싱 가능) 입니다. 영구 보관은 DB 단계뿐 이고, 나머지는 스쳐 갑니다.
8. 핵심 용어
| 용어 |
정의 |
| 관계형 DB / 스키마 |
테이블·행·컬럼 구조 / DB 구조 정의 |
| PK / FK |
각 행 고유 식별 / 다른 테이블 PK 참조(연결) |
| 정규화 / 역정규화 |
중복 제거·일관성↑ / 성능 위해 의도적 중복 |
| 1NF·2NF·3NF |
원자값 / 부분 종속 제거 / 이행 종속 제거 |
| 인덱스 / JOIN |
검색 색인 / 두 테이블 연결 조회(INNER·LEFT/RIGHT) |
| 트랜잭션 / ACID |
함께 성공·실패 / 원자·일관·격리·지속 |
| NoSQL(문서·키값·분산) |
유연 저장 / MongoDB·Redis·DynamoDB |
| 객체 스토리지 / 버킷 / 오브젝트 |
파일 저장(S3) / 저장 단위 / 저장된 파일 |
| 서명된 URL / CDN |
시간 제한 접근 링크 / 엣지 배포 |
| BaaS / RLS |
백엔드 통합 제공 / 행 단위 접근 제어 |
| 캐싱 / TTL |
빠른 저장소 복사 / 자동 만료 시간 |
| 마이그레이션 / 다운타임 / 롤백 |
구조 변환 / 중단 시간 / 이전 버전 복귀 |
| OLTP / OLAP / 샤딩 / 복제 / 백업 / 감사 로그 |
실시간 처리 / 분석 처리 / 분산 저장 / 동일 유지 / 복사 보존 / 변경 기록 |
9. 한눈에 정리
- 데이터는 정형·반정형·비정형·시계열 로 나뉘고, 종류가 저장소(관계형·문서형·객체·시계열)를 정한다.
- 관계형 DB의 핵심 = 외래키(관계) · 정규화(중복 제거) · 인덱스(속도) · 트랜잭션(ACID).
- 파일은 객체 스토리지 + CDN, 권한은 코드가 아니라 DB(RLS) 에서 강제.
- BaaS(Supabase 등) 로 빠르게 시작하고 커지면 자체 스택으로. 영구 보관은 DB 단계뿐.
자가 진단
① 네 데이터 종류를 구분할 수 있나 ② 간단한 ERD(엔티티·속성·관계)를 그릴 수 있나 ③ 정규화의 의도를 설명할 수 있나 ④ RLS로 "누가 어떤 행을" 보는지 설계할 수 있나.
다음 강 예고
입문(기술 기초) 5강. 인프라·배포·보안 — 서비스가 실제로 도는 환경. 클라우드·컨테이너·CI/CD·모니터링과 보안(암호화·인증·비밀 관리)을 봅니다.
※ 원문(선수 M4)을 구성·내용 보존 원칙으로 재구성하고 존댓말로 통일했으며, 다이어그램을 보강(4종류·ERD·객체스토리지+CDN·RLS·데이터 일생)하고 깨진 이미지 참조를 교체했습니다. 도구·플랫폼은 시점에 따라 달라질 수 있습니다.
1부 · 기술 기초
입문(기술 기초) 5강. 인프라 · 배포 · 보안
유형: 이론 (다이어그램 보강판) · 읽는 데 약 30분
선수: 2~4강. 러닝 예시 = 이벤트 RSVP(개요·아키텍처는 러닝 예시 참조).
이 강을 마치면: ① 인프라 4계층(IaaS·PaaS·SaaS·BaaS)을 구분한다 ② 도메인·DNS·HTTPS 연결을 이해한다 ③ 흔한 보안 위협 5가지와 시크릿 관리를 안다 ④ 모니터링·개인정보 법규의 요점을 잡는다.
0. 들어가며
웹 애플리케이션이 실제로 사람들의 손에 닿으려면 어디에, 어떻게, 누구의 접근을 허용할지 를 정해야 합니다. 이 강은 클라우드 인프라부터 도메인·HTTPS, 보안 위협, 시크릿 관리, 모니터링, 개인정보 법규까지 훑습니다. (이벤트 RSVP 시스템을 예로 의사결정을 따라갑니다.)
1. 인프라 4계층 — IaaS · PaaS · SaaS · BaaS
클라우드 인프라는 추상화 수준 에 따라 네 계층으로 나뉩니다.

| 계층 |
제공 |
내 관리 책임 |
사례 |
시작 비용 |
| IaaS |
CPU·메모리·스토리지·네트워크 |
OS·DB·앱까지 거의 전부 |
AWS EC2·GCE |
높음 |
| PaaS |
개발·배포 환경 |
앱 코드만 |
Vercel·Netlify·Heroku |
중간 |
| BaaS |
DB·인증·스토리지 |
프론트엔드만 |
Supabase·Firebase |
낮음 |
| SaaS |
완성된 소프트웨어 |
없음(사용자로 사용) |
Google Workspace·Slack |
낮음 |
위로 갈수록 관리 책임과 자유도가 함께 줄어듭니다. 팀 1~3명·인프라 경험 없음 이면 PaaS(Vercel)+BaaS(Supabase), DevOps 인력이 있는 10명+ 이면 IaaS(AWS/GCP)+쿠버네티스가 무난합니다.
RSVP 예: 프론트엔드는 PaaS(Vercel), 데이터는 BaaS(Supabase) — 별도 인프라 팀이 필요 없습니다.
2. 클라우드 사업자 — AWS · GCP · Azure · Cloudflare
| 사업자 |
강점 |
약점 |
적합 |
| AWS |
서비스 수·성숙도·커뮤니티 최고 |
가격 복잡, 한국 리전 비쌈 |
대규모·엔터프라이즈 |
| GCP |
AI/ML·가격 투명·Firebase |
서비스 수·커뮤니티 상대적 작음 |
데이터 분석·스타트업 |
| Azure |
Windows/Office 생태계·기업 지원 |
학습곡선·가격 |
MS 도구 쓰는 기업 |
| Cloudflare |
CDN·DNS·WAF 통합·저렴·성능 |
컴퓨팅만으론 부족 |
보안·성능 중심 |
의사결정은 대략 기술 스택(Next.js→Vercel, Python→GCP), 예산(월 $100 이하→Vercel+Supabase, $1,000+→AWS), 규정(금융·의료→AWS/Azure 한국 리전)으로 갈립니다. (한국 리전은 AWS·GCP·Azure 모두 서울에 있습니다.)
3. 풀스택 PaaS — Vercel · Netlify · Render · Railway
초기 팀은 Git 저장소와 연동해 자동 배포(CI/CD)되는 풀스택 PaaS가 편합니다.
| PaaS |
강점 |
약점 |
| Vercel |
Next.js 최적화·Edge·빠름 |
백엔드 복잡 시 비용↑ |
| Netlify |
정적 사이트·폼 처리 내장 |
백엔드 제약 |
| Render |
DB·백엔드 풀스택·가격 명확 |
무료 tier 콜드 스타트 |
| Railway |
저렴·모든 서비스 포함·DX 우수 |
한국 리전 없음 |
선택: 정적=Netlify, Next.js=Vercel, 백엔드 포함 풀스택=Render/Railway 또는 Supabase+Vercel.
RSVP 예: 프론트=Vercel, 백엔드=Render(또는 Vercel Functions), DB=Supabase. 트래픽이 적을 때 월 $50~100 수준.
4. 도메인과 DNS

도메인 은 '내 집 주소'입니다. 사용자가 rsvp.example.com 을 입력하면, DNS(전화번호부)가 이름을 IP 주소로 바꿔 서버로 연결합니다. DNS 레코드는 다섯 가지가 핵심입니다.
| 레코드 |
용도 |
예 |
| A / AAAA |
IPv4 / IPv6 주소 매핑 |
example.com → 192.0.2.1 |
| CNAME |
별칭(다른 도메인 가리킴) |
www → example.com |
| MX |
메일 서버 |
@ → Google Workspace |
| TXT |
검증(SPF·DKIM 등) |
v=spf1 … |
서브도메인(api.rsvp.example.com)은 각각 다른 서버로 보낼 수 있고, Apex(example.com 자체)는 CNAME을 쓸 수 없어 A 레코드를 씁니다. 도메인은 국내 대상이면 .kr(KISA), 글로벌이면 .com(Cloudflare·Namecheap 등)을 씁니다.
실제 도메인 관리 화면에 등록하는 레코드는 이런 표 한 장입니다(RSVP 배포 예). "이름 → 종류 → 값"만 채우면 됩니다.
; 타입 이름 값(가리키는 곳)
A rsvp 76.76.21.21 ; rsvp.ourcompany.com → 호스팅 서버 IP
CNAME www rsvp.ourcompany.com; www로 와도 rsvp로 연결
MX @ aspmx.google.com ; 메일은 Google Workspace로
TXT @ "v=spf1 include:_spf.google.com ~all" ; 메일 위조 방지(SPF)
5. HTTPS · SSL/TLS

HTTP는 평문 이라 공용 와이파이 등에서 도청되면 비밀번호가 노출됩니다. HTTPS 는 전송 구간을 암호화하고, SSL/TLS 인증서 로 "이 사이트가 진짜 example.com"임을 증명합니다(검색 순위에도 우대).
인증서는 요청(CSR) → 인증기관(CA, 예: Let's Encrypt)이 도메인 소유 검증 → 발급 → 설치 → 갱신 을 거칩니다. 무료 CA는 90일 주기라 자동 갱신 이 필수인데(업계 갱신 주기가 점점 짧아지는 추세), PaaS(Vercel·Netlify) 는 발급·갱신을 자동 처리해 신경 쓸 필요가 없습니다.

⚠️ 흔한 실수 — ① 갱신 실패로 사이트가 갑자기 안 열림 ② 와일드카드(*.example.com)가 example.com 자체는 커버 못 함 ③ 인증서-도메인 불일치(www 접속 시 경고) ④ 혼합 콘텐츠(HTTPS 페이지에서 HTTP 리소스 로드) ⑤ 자체 서명 인증서를 프로덕션에 사용.
6. 흔한 보안 위협 5

- SQL Injection — 입력에 SQL을 끼워 DB를 조작(예:
admin' -- 로 비밀번호 확인 무력화). 막기: 매개변수화 쿼리(WHERE email = ?)·ORM.
- XSS(Cross-Site Scripting) — 댓글 등에 악성 스크립트를 주입해 다른 사용자의 쿠키·세션을 탈취. 막기: HTML 이스케이프·CSP(스크립트 출처 제한).
- CSRF(Cross-Site Request Forgery) — 사용자가 모르게 그의 계정으로 요청(숨겨진 폼 등). 막기: CSRF 토큰·SameSite 쿠키.
- 계정 탈취(Credential Stuffing) — 유출된 비번 목록으로 무작위 로그인. 막기: MFA·시도 제한·강한 비밀번호.
- 민감정보 노출 —
.env·API 키를 Git에 커밋해 공개(도용·과금 폭탄). 막기: .gitignore·비밀 스캔·즉시 키 회전.
illustration(개념): 취약한 코드는 사용자 입력을 문자열로 이어 붙여 쿼리를 만들고, 안전한 코드는 값을 매개변수 로 분리해 넘깁니다.
취약: SELECT * FROM users WHERE email = '<입력 그대로>'
안전: SELECT * FROM users WHERE email = ? (값은 따로 전달)

7. 환경 변수 · 시크릿 관리

환경 변수 는 코드 밖에서 값을 설정하는 방법으로, 개발·테스트·프로덕션마다 다르게 줄 수 있습니다(DATABASE_URL·API_KEY 등). 비밀은 코드에서 멀수록 안전합니다.
| 보관 위치 |
위험도 |
| 코드 안 |
극위험(커밋되면 공개) |
.env(로컬) |
위험(.gitignore 필수) |
| 환경 변수(배포 패널) |
낮음 |
| Secret Manager(암호화·회전·감사) |
최저 |
권장: 개발 = .env(+.gitignore), 배포 = 플랫폼 환경 변수 패널, 엔터프라이즈 = AWS Secrets Manager·Supabase Vault. 키는 주기적으로 회전(외부 API 키·AWS 키 90일, DB 비번 180일 등)합니다.
실제 파일은 아래처럼 생겼습니다. .env에 값을 적고, .gitignore에 .env를 넣어 Git에 올라가지 않게 막는 것이 핵심입니다.
# .env (로컬 개발용 — 절대 Git에 커밋하지 않음)
DATABASE_URL=postgresql://user:pass@localhost:5432/rsvp
SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...
JWT_SECRET=길고-무작위인-비밀문자열-절대-공유금지
RESEND_API_KEY=re_xxxxxxxxxxxx
# .gitignore (이 목록의 파일은 Git이 무시 → 유출 방지)
.env
.env.local
node_modules/
코드에서는 값을 직접 쓰지 않고 process.env.JWT_SECRET(Node) 또는 os.environ["JWT_SECRET"](파이썬)처럼 이름으로 불러옵니다. 배포할 때는 같은 이름을 Vercel·Supabase·AWS의 환경 변수 패널에 등록하면 됩니다.
⚠️ .env를 실수로 커밋했다면 — ① 해당 키를 즉시 무효화(회전) ② Git 히스토리 정리(BFG 등) ③ 새 저장소 이전. 한번 노출된 키는 이미 유출된 것 으로 간주해야 합니다.
8. 모니터링 · 로깅 · 알림
무엇을 볼지 정하는 것이 먼저입니다.
| 항목 |
정상 / 주의 / 심각(예) |
| 트래픽(req/s) |
<100 / 100~500 / >500 |
| 에러율(5xx) |
<1% / 1~5% / >5% |
| 응답시간 |
<200ms / 200~1000ms / >1000ms |
| CPU·메모리 |
<70% / 70~90% / >90% |
| DB 쿼리 시간 |
<50ms / 50~200ms / >200ms |
| 비즈니스 지표 |
신청 수·가입 수 추이 |
도구는 Sentry(에러 추적)·Datadog(통합 모니터링)·Grafana(오픈소스 시각화)·Vercel Analytics 등이 있고, 알림은 Slack(즉시)·이메일(기록)·SMS(야간 긴급)·PagerDuty(온콜 자동 호출)로 보냅니다.
장애 대응(개념) — 탐지(모니터링) → 격리(문제 부분 오프라인) → 복구(백업에서 복원) → 회고(원인 분석) → 재발 방지(정책·교육) 의 순서로 다룹니다. 관련 지표로 RTO(복구 목표 시간)·RPO(허용 데이터 손실)·SLA(가용성 약정, 예 99.9%=월 43분 장애 용인)를 미리 정해 둡니다.

9. 개인정보 · 법규
- 개인정보보호법(PIPA, 한국) — 수집(목적 명시·동의)·이용(목적 내)·보관(암호화·접근 제한)·파기(목적 완료 후 삭제)를 규정합니다. 위반 시 형사·행정 처벌이 있고, 유출 시 신고 의무가 있습니다.
- GDPR(EU) — 한국 회사도 EU 사용자를 대상으로 하면 적용됩니다. 접근·정정·삭제(잊힐 권리)·제한·이동 권리를 보장해야 하며, 위반 시 과징금이 매우 무겁습니다(연 매출 4% 또는 2,000만 유로 중 큰 금액). 미국 클라우드로 EU 데이터를 옮기면 데이터 이전 근거(현행 EU-US Data Privacy Framework 등)를 확인해야 합니다.
- KISA 권고(한국) — 개인정보 암호화(AES-256 이상)·접근 제어(필요한 사람만)·감사 로그·침해 시 신고.
RSVP 예 동의 문구 — "이메일 수집·이용 동의 / 휴대폰은 SMS 알림용으로만 / 개인정보는 이벤트 종료 후 30일 내 삭제" 처럼 수집 목적·이용 범위·보관 기간 을 명확히 밝힙니다.
10. RSVP 인프라 구성 (개념 요약)
앞의 결정을 이벤트 RSVP에 적용하면 다음과 같습니다(개념 — 구체 명령·코드는 생략).
| 요소 |
선택 |
비고 |
| 도메인 |
rsvp.ourcompany.com (A 레코드 → 호스팅 IP) |
국내면 .kr, 글로벌이면 .com |
| 배포 |
프론트=Vercel · DB=Supabase |
자동 CI/CD |
| HTTPS |
Let's Encrypt (PaaS 자동) |
갱신 자동 |
| 시크릿 |
배포 플랫폼 환경 변수 패널 |
코드/Git에 두지 않음 |
| 보안 |
매개변수화 쿼리·이스케이프·SameSite·MFA |
다층 방어 |
| 모니터링 |
Sentry + 분석 도구 → Slack 알림 |
초기부터 도입 |
| 개인정보 |
동의 체크 + 처리방침 페이지 |
수집·목적·보관기간 명시 |
11. AWS 주요 서비스 둘러보기
이 교재의 예시는 배포를 Vercel + Supabase로 잡았지만, 국내외 많은 서비스가 AWS(Amazon Web Services) 위에서 돌아갑니다. AWS는 200개가 넘는 서비스를 제공하는데, 이름이 워낙 많아 처음엔 압도되기 쉽습니다. 기획자에게 필요한 건 전부 외우는 게 아니라, 역할별로 대표 서비스 몇 개를 알아 두는 것입니다. 그러면 개발팀의 견적서나 아키텍처 문서에 등장하는 약어를 읽어낼 수 있습니다.

역할별로 자주 쓰는 서비스는 다음과 같습니다.
| 역할 |
대표 서비스 |
한 줄 설명 |
| 컴퓨트(실행) |
EC2 · Lambda · ECS/EKS · Fargate |
가상 서버 · 서버리스 함수 · 컨테이너 실행 |
| 스토리지(저장) |
S3 · EBS · EFS · Glacier |
파일·이미지 저장(S3) · 디스크 · 공유 파일 · 장기 보관 |
| 데이터베이스 |
RDS/Aurora · DynamoDB · ElastiCache · Redshift |
관계형(PostgreSQL 등) · NoSQL · 캐시 · 분석 웨어하우스 |
| 네트워크·전송 |
VPC · Route 53 · CloudFront · ELB · API Gateway |
가상 네트워크 · DNS · CDN · 로드밸런서 · API 입구 |
| 보안·인증 |
IAM · Cognito · KMS · Secrets Manager · WAF/Shield |
권한 · 사용자 인증 · 암호화 키·비밀 · 웹 방화벽/DDoS 방어 |
| 관측·메시징·CI/CD |
CloudWatch · SQS/SNS · ECR · CodePipeline/CodeBuild |
모니터링·로그·알림 · 큐/알림 · 이미지 저장 · 배포 자동화 |
앞 강들에서 배운 개념이 대부분 AWS 서비스로 1:1 대응됩니다. 4강의 객체 스토리지 = S3, 관계형 DB = RDS/Aurora, 캐싱 = ElastiCache, 5강의 DNS = Route 53, CDN = CloudFront, 시크릿 관리 = Secrets Manager, 모니터링 = CloudWatch 입니다. 이름만 다를 뿐 하는 일은 같습니다.
11.1 AWS Amplify — 위 서비스들을 하나로 묶은 풀스택 도구
여러 서비스를 따로 조립하는 대신, AWS Amplify는 프론트엔드·백엔드·호스팅을 한 도구로 묶어 줍니다. 이 교재가 쓰는 Vercel + Supabase 조합에 대응하는 'AWS 한 지붕' 선택지라고 보면 됩니다. 현재의 Amplify(Gen 2)는 TypeScript 코드로 백엔드를 정의하는 코드-우선 방식입니다. Amplify가 제공하는 것을 정리하면 다음과 같습니다.
- 인증(Authentication) — 로그인·회원가입·소셜 로그인을 Amazon Cognito 기반으로 제공. RSVP라면 참석자 로그인이 여기에 해당합니다.
- 데이터(Data) API — 타입이 완전히 잡힌 실시간 API를 AWS AppSync(GraphQL) + Amazon DynamoDB(NoSQL)로 자동 구성.
- 스토리지(Storage) — 파일·이미지 업로드를 Amazon S3에 저장. RSVP의 포스터·증명 파일이 여기에 올라갑니다.
- 함수(Functions) — 서버리스 백엔드 로직을 AWS Lambda로 실행. 마감·정원 같은 규칙 처리에 사용.
- 호스팅(Amplify Hosting) — 프론트엔드 웹앱 배포. Git 브랜치별 자동 배포(풀스택 브랜치 배포) 를 지원해, 브랜치 하나가 환경 하나에 1:1로 대응됩니다.
- 클라우드 샌드박스 — 개발자마다 격리된 클라우드 개발 환경을 받아 자기 변경을 실제 AWS 백엔드에서 바로 테스트. (Gen 1 대비 반복 배포가 최대 8배 빠릅니다.)
- 콘솔 — 빌드·호스팅 설정(커스텀 도메인)·배포된 리소스(데이터 브라우저·사용자 관리)·환경 변수/시크릿을 한 화면에서 관리.
- CDK 확장 — 필요하면 AWS CDK로 200개가 넘는 AWS 서비스를 그대로 끌어와 붙일 수 있어, 커지더라도 도구를 갈아탈 필요가 없습니다.
💡 기획자 포인트 — Vercel + Supabase는 초기 프로토타입을 가장 빠르게 띄우는 조합이고, AWS Amplify는 이미 사내 인프라가 AWS로 통일돼 있거나 인증·데이터·파일을 한 계정·한 청구서로 묶고 싶을 때 유리합니다. 둘 다 "여러 인프라 조각을 자동으로 엮어 준다"는 점에서 성격이 같습니다(1절의 PaaS/BaaS).
12. 배포 시나리오별 추천 조합
앞에서 배포 도구(§3의 PaaS, §11의 AWS)를 훑었으니, 이제 "그래서 어떤 상황에 무엇을 고르면 되는가"를 정리합니다. 크게 개인/사이드 프로젝트와 회사의 가벼운 배포 두 갈래로 나눠 추천합니다.

12.1 개인·사이드 프로젝트
혼자 빠르게 만들어 띄운다면 GitHub + Supabase + Vercel 조합을 추천합니다. GitHub으로 코드와 버전을 관리하고, Supabase(BaaS)로 DB·인증·스토리지를 한 번에 해결하며, Vercel(PaaS)로 프론트엔드를 배포하면 Git에 푸시할 때마다 자동으로 재배포됩니다. 대부분 무료 티어로 충분하고, 이 교재의 RSVP 예시가 바로 이 조합입니다.
더 가벼운 경우도 있습니다.
- 정적 페이지(화면만 보여주면 되고 DB가 필요 없는 경우) — 굳이 서버가 필요 없습니다. GitHub Pages만으로 무료로 정적 사이트를 배포할 수 있습니다. 소개 페이지·포트폴리오·행사 안내처럼 데이터가 고정된 화면에 알맞습니다.
- 정적인데 입력값 수집만 필요한 경우(신청 폼 등) — 전체 백엔드를 세우지 않고도 처리할 수 있습니다. Google Sheets를 간이 데이터베이스처럼 쓰고, Apps Script로 폼 제출 데이터를 시트에 기록·연동하면 됩니다. 서버 없이 "정적 페이지 + 폼 수집"이 완성됩니다. RSVP도 아주 초기라면 이 방식으로 신청만 받아볼 수 있습니다.
12.2 회사의 가벼운 배포
사내 인프라가 이미 AWS로 통일되어 있다면, 개인 조합 대신 AWS 생태계로 묶는 편이 관리가 편합니다. 추천 조합은 GitHub + AWS Amplify + Supabase + AWS 관리형 서비스(Lambda 등) 입니다. GitHub으로 코드를 관리하고, AWS Amplify로 프론트엔드 호스팅과 백엔드 정의를 맡기며(§11.1), DB는 Supabase를 그대로 쓰거나 Amplify 기본 데이터로 대체하고, 커스텀 백엔드 로직은 Lambda 같은 AWS 관리형 서비스로 처리합니다. 인증·데이터·파일·컴퓨팅을 한 계정·한 청구서로 묶을 수 있어, 보안·정산·감사 측면에서 회사에 유리합니다.
💡 이 셋업·배포는 Claude가 진행합니다 — 위 조합의 저장소 생성, 환경 변수 설정, 빌드, 배포까지의 과정은 Cowork·Code에게 자연어로 지시하면 대신 수행합니다. 기획자는 "무엇을 어디에 배포할지"만 정하고, 반복적인 배포 작업은 에이전트에 위임하는 것이 이 교재가 지향하는 방식입니다.
정리하면, 혼자·빠르게면 GitHub+Supabase+Vercel, 화면만이면 GitHub Pages, 정적+폼 수집이면 Google Sheets+Apps Script, 회사가 이미 AWS면 GitHub+Amplify+Supabase+Lambda 조합입니다. Vercel+Supabase와 AWS Amplify는 둘 다 여러 인프라 조각을 자동으로 엮어 준다는 점에서 성격이 같습니다(§1의 PaaS/BaaS).
13. 핵심 용어
| 용어 |
정의 |
| IaaS/PaaS/SaaS/BaaS |
인프라 / 플랫폼 / 소프트웨어 / 백엔드를 서비스로 |
| 도메인 / DNS / A·CNAME·MX·TXT |
주소 / 이름→IP 변환 / 레코드 종류 |
| HTTP / HTTPS / SSL·TLS / 인증서 |
평문 / 암호화 / 암호화 프로토콜 / 신원 증명 |
| Let's Encrypt |
무료 인증서 발급 기관 |
| 환경 변수 / Secret Manager / 회전 |
코드 밖 값 / 비밀 저장소 / 키 교체 |
| SQL Injection / XSS / CSRF |
SQL 삽입 / 스크립트 삽입 / 무단 요청 공격 |
| 매개변수화 쿼리 / CSP / SameSite |
SQLi 방어 / XSS 방어 / CSRF 방어 |
| 모니터링 / 로깅 / 알림 |
상태 감시 / 기록 / 담당자 호출 |
| RTO / RPO / SLA / MTTR |
복구 목표 시간 / 허용 손실 / 가용성 약정 / 평균 복구 시간 |
| PIPA / GDPR |
개인정보보호법(한국) / EU 개인정보법 |
| Blue-Green / Canary 배포 |
두 환경 교대 / 일부에게만 먼저 |
| AWS 주요 서비스 |
EC2·Lambda(컴퓨트) · S3(스토리지) · RDS/DynamoDB(DB) · Route 53·CloudFront(전송) · IAM·Cognito(보안) · CloudWatch(관측) |
| AWS Amplify |
인증·데이터·스토리지·함수 + 호스팅을 코드로 묶는 AWS 풀스택 도구(Gen 2) |
14. 한눈에 정리
- 인프라는 IaaS→PaaS→BaaS→SaaS 로 갈수록 관리 책임↓·자유도↓. 초기 팀은 PaaS+BaaS.
- 이름은 도메인·DNS(A·CNAME·MX·TXT) 로 서버에 연결, 전송은 HTTPS(인증서·자동 갱신) 로 암호화.
- 보안 5위협 = SQLi·XSS·CSRF·계정 탈취·시크릿 노출, 각각 매개변수화·이스케이프·토큰/SameSite·MFA·키 회전으로 방어.
- 비밀은 코드에서 멀수록 안전. 모니터링·알림·RTO/RPO/SLA 로 장애를 관리하고, 개인정보 법규(PIPA·GDPR) 를 준수.
- 많은 서비스가 AWS 위에서 돌아갑니다. 역할별 대표 서비스(S3·RDS·Route 53·CloudFront·IAM·CloudWatch)를 알아 두고, 이를 한 번에 묶는 AWS Amplify(인증·데이터·스토리지·함수+호스팅)는 Vercel+Supabase에 대응하는 'AWS 한 지붕' 선택지입니다.
- 배포 시나리오: 혼자·빠르게=GitHub+Supabase+Vercel, 화면만=GitHub Pages, 정적+폼 수집=Google Sheets+Apps Script, 회사가 AWS면=GitHub+Amplify+Supabase+Lambda(셋업·배포는 Claude가 진행).
자가 진단
① IaaS와 PaaS의 차이를 설명할 수 있나 ② 도메인을 호스팅에 연결하려면 어떤 DNS 레코드가 필요한가 ③ SQL Injection을 어떻게 막나 ④ API 키가 Git에 노출됐을 때의 대응 순서.
다음 강 예고
여기까지가 입문(기술 기초) — 프론트·백·데이터·인프라의 개념 지도입니다. 이제 코딩 with Claude 초급 으로 넘어가, Claude(Cowork·Code)로 무엇을·어떻게 시키는지 봅니다.
※ 원문(선수 M5)을 구성·내용 보존 원칙으로 재구성하고 존댓말로 통일했으며, 실습형 배포 튜토리얼은 개념 요약으로 대체하고 다이어그램을 보강(4계층·DNS·HTTPS·보안 위협·시크릿)했습니다. 사업자·도구·법규·가격은 시점에 따라 달라질 수 있습니다.