웹 서비스 설계와 아키텍처¶
우리가 만들 것은 무엇인가?¶
앞서 API가 프로그램끼리 대화하는 방법임을 배웠습니다.
이제 질문이 생깁니다: 그 API를 어디에, 어떻게 올려야 할까요?
웹 서비스를 만든다는 것은 단순히 코드를 작성하는 게 아닙니다.
코드가 돌아갈 구조, 즉 아키텍처(Architecture)를 먼저 설계해야 합니다.
웹 서비스란?¶
웹 서비스 = 인터넷 브라우저(또는 앱)를 통해 접근할 수 있는 소프트웨어
| 예시 | 설명 |
|---|---|
| 인스타그램 | 사진을 올리고 공유하는 소셜 서비스 |
| 당근마켓 | 중고 물품을 사고파는 거래 서비스 |
| 유튜브 | 동영상을 업로드하고 시청하는 서비스 |
| 카카오맵 | 지도와 장소 정보를 제공하는 서비스 |
이 서비스들은 겉보기엔 달라 보이지만, 내부 구조는 놀랍도록 비슷합니다.
클라이언트 - 서버 구조¶
모든 웹 서비스의 뼈대는 클라이언트-서버(Client-Server) 구조입니다.
[클라이언트] ──요청(Request)──▶ [서버]
◀──응답(Response)──
| 역할 | 클라이언트 | 서버 |
|---|---|---|
| 정의 | 요청을 보내는 쪽 | 요청을 받아 처리하는 쪽 |
| 예시 | 브라우저, 스마트폰 앱 | AWS EC2, 회사 컴퓨터 |
| 위치 | 사용자 기기 | 인터넷 어딘가 (항상 켜져 있음) |
| 주도권 | 먼저 요청함 | 요청이 올 때만 응답함 |
편의점 비유¶
클라이언트는 손님, 서버는 편의점입니다.
손님이 편의점에 들어와서 물건을 집어야(요청) 계산원이 계산해줍니다(응답).
편의점은 손님이 오지 않아도 항상 열려 있습니다.
프론트엔드 vs 백엔드¶
서버 내부로 들어가면, 웹 서비스는 크게 두 영역으로 나뉩니다.
사용자
│
▼
[프론트엔드] ──API 요청──▶ [백엔드] ──쿼리──▶ [데이터베이스]
HTML/CSS ◀──JSON── Python/JS MySQL/PostgreSQL
JavaScript
프론트엔드 (Frontend)¶
사용자가 직접 보고 상호작용하는 부분
- 화면에 그려지는 UI (버튼, 입력창, 목록)
- 브라우저에서 실행됨
- 언어: HTML, CSS, JavaScript (React, Vue 등)
- 역할: 데이터를 보기 좋게 표현하고, 사용자 입력을 받아 API로 전달
백엔드 (Backend)¶
사용자 눈에 보이지 않지만 핵심 로직이 돌아가는 부분
- 비즈니스 로직 처리 (결제, 인증, 추천 알고리즘)
- 서버에서 실행됨
- 언어: Python (FastAPI, Django), JavaScript (Node.js), Java, Go 등
- 역할: API를 제공하고, 데이터베이스를 읽고 씀
데이터베이스 (Database)¶
데이터를 영구적으로 저장하는 곳
- 서버가 꺼져도 데이터는 남아 있음
- 종류: MySQL, PostgreSQL (표 형태), MongoDB (문서 형태)
레스토랑에 비유하면:
프론트엔드 = 홀 (손님이 앉아 메뉴를 보는 곳)
백엔드 = 주방 (실제 요리가 이루어지는 곳)
데이터베이스 = 창고 (재료를 보관하는 곳)
아키텍처 설계란?¶
아키텍처(Architecture) = 시스템의 구성 요소와 그 관계를 정의한 구조
건물을 짓기 전에 설계도를 그리듯, 코드를 짜기 전에 아키텍처를 먼저 설계합니다.
왜 설계가 먼저인가?¶
코드부터 짜면 생기는 문제:
처음엔 잘 돌아가는 것 같음
↓
기능이 추가될수록 코드가 얽힘
↓
버그를 고치면 다른 곳이 터짐
↓
결국 처음부터 다시 짜야 함
설계를 먼저 하면:
요구사항 명확화
↓
구성 요소 분리
↓
각 부분을 독립적으로 개발
↓
유지보수와 기능 추가가 쉬움
웹 서비스 설계 5단계¶
1단계: 서비스 정의 — "무엇을 만드나?"¶
만들려는 서비스를 한 문장으로 정의합니다.
예: "사용자가 할 일 목록을 등록하고 관리하는 Todo 서비스"
2단계: 사용자 시나리오 — "누가 어떻게 쓰나?"¶
실제 사용자의 행동 흐름을 나열합니다.
1. 회원가입 / 로그인
2. 할 일 추가하기
3. 할 일 목록 보기
4. 할 일 완료 체크하기
5. 할 일 삭제하기
3단계: 데이터 모델 — "무엇을 저장하나?"¶
서비스에 필요한 데이터를 정의합니다.
사용자(User)
├── id (고유번호)
├── email (이메일)
├── password (비밀번호)
└── created_at (가입일)
할 일(Todo)
├── id (고유번호)
├── user_id (작성한 사용자)
├── title (제목)
├── is_done (완료 여부)
└── created_at (작성일)
4단계: API 설계 — "어떤 요청을 받을 것인가?"¶
2단계의 시나리오를 API로 변환합니다.
POST /auth/signup 회원가입
POST /auth/login 로그인
GET /todos 내 할 일 목록 조회
POST /todos 할 일 추가
PATCH /todos/{id} 할 일 수정 (완료 체크)
DELETE /todos/{id} 할 일 삭제
5단계: 기술 스택 선택 — "어떤 도구를 쓸 것인가?"¶
각 계층에 쓸 기술을 결정합니다.
| 계층 | 선택지 | 우리가 쓸 것 |
|---|---|---|
| 프론트엔드 | React, Vue, 바닐라 JS | (과정에 따라 결정) |
| 백엔드 | FastAPI, Django, Express | FastAPI (Python) |
| 데이터베이스 | PostgreSQL, MySQL, SQLite | SQLite (개발용) |
| 배포 | AWS, GCP, Railway, Render | Railway / Render |
실제 아키텍처 다이어그램¶
우리가 만들 Todo 서비스의 전체 구조:
브라우저 (사용자)
│
│ HTTP 요청 (JSON)
▼
┌─────────────────────────────┐
│ FastAPI 서버 │
│ ┌───────────────────────┐ │
│ │ 라우터 (Router) │ │ ← URL별로 요청을 분류
│ │ POST /todos │ │
│ │ GET /todos │ │
│ └──────────┬────────────┘ │
│ │ │
│ ┌──────────▼────────────┐ │
│ │ 서비스 (Service) │ │ ← 비즈니스 로직
│ │ 할 일 추가 로직 │ │
│ │ 권한 확인 로직 │ │
│ └──────────┬────────────┘ │
│ │ │
│ ┌──────────▼────────────┐ │
│ │ DB 계층 (ORM) │ │ ← 데이터베이스 접근
│ └──────────┬────────────┘ │
└─────────────┼───────────────┘
│
┌─────────▼──────────┐
│ SQLite DB │
│ users 테이블 │
│ todos 테이블 │
└────────────────────┘
관심사 분리 (Separation of Concerns)¶
좋은 아키텍처의 핵심 원칙입니다.
각 부분은 자신의 역할만 한다.
| 계층 | 역할 | 하지 말아야 할 것 |
|---|---|---|
| 라우터 | URL 매핑, 요청/응답 처리 | DB 직접 접근 |
| 서비스 | 비즈니스 로직 | HTTP 세부사항 처리 |
| DB 계층 | 데이터 저장/조회 | 비즈니스 판단 |
왜 중요한가? 역할이 분리되면:
- 하나를 바꿔도 다른 곳이 영향을 받지 않음
- 각 부분을 따로 테스트할 수 있음
- 팀으로 작업할 때 충돌이 줄어듦
요구사항 명세서 (SRS) 작성하기¶
아키텍처를 설계하기 전에, 무엇을 만들 것인지부터 명확하게 정의합니다.
이것을 SRS(Software Requirements Specification)라고 합니다.
최소 SRS 템플릿¶
# 서비스명
## 1. 서비스 개요
한 문장으로: 누구를 위해, 무엇을 하는 서비스인가?
## 2. 사용자 역할
- 비로그인 사용자: 할 수 있는 것
- 로그인 사용자: 할 수 있는 것
## 3. 주요 기능 (Must)
- 나는 [사용자]로서, [기능]을 하고 싶다
- [ ] 인수 조건 1
- [ ] 인수 조건 2
## 4. 범위 밖 (Out of Scope)
- 이번 버전에서 만들지 않는 것
## 5. 기술 스택
백엔드: FastAPI
DB: SQLite
실습 미션¶
미션 1: 서비스 정의하기¶
아래 중 하나를 골라 (또는 직접 생각해서) 서비스를 한 문장으로 정의하세요.
- 독서 기록 서비스 (읽은 책, 읽는 중, 읽고 싶은 책 관리)
- 용돈 기입장 (수입/지출 기록 및 잔액 확인)
- 스터디 플래너 (과목별 공부 시간 기록)
미션 2: 사용자 시나리오 작성¶
미션 1에서 고른 서비스의 사용자 시나리오를 5개 이상 작성하세요.
예) 독서 기록 서비스
1. 회원가입 / 로그인
2. 책 추가하기 (제목, 저자, 상태)
3. 내 책 목록 보기
4. 읽는 중 → 읽음으로 상태 변경
5. 책 삭제하기
6. (심화) 별점 및 한줄 감상 남기기
미션 3: 데이터 모델 설계¶
미션 1의 서비스에 필요한 데이터를 설계하세요.
힌트 — 각 항목에 대해 아래를 생각해보세요:
- 이 데이터를 식별하는 고유한 값은? (id)
- 어떤 사용자의 데이터인지 알 수 있어야 하는가? (user_id)
- 저장해야 하는 정보는 무엇인가?
- 언제 만들어졌는지 알아야 하는가? (created_at)
미션 4: API 설계¶
미션 2의 시나리오를 HTTP 메서드와 URL로 변환하세요.
형식: [메서드] [URL] — [설명]
예)
POST /books — 책 추가
GET /books — 내 책 목록 조회
PATCH /books/{id} — 책 상태 변경
DELETE /books/{id} — 책 삭제
미션 5 (심화): 미니 SRS 작성¶
미션 1~4를 합쳐서 하나의 SRS 문서를 작성하세요.
마크다운 파일(.md)로 작성하면 더 좋습니다.
핵심 요약¶
| 개념 | 설명 |
|---|---|
| 웹 서비스 | 인터넷으로 접근하는 소프트웨어 |
| 클라이언트-서버 | 요청하는 쪽과 응답하는 쪽의 분리 |
| 프론트엔드 | 사용자에게 보이는 화면 (브라우저에서 실행) |
| 백엔드 | 비즈니스 로직과 API 처리 (서버에서 실행) |
| 데이터베이스 | 데이터를 영구적으로 저장하는 곳 |
| 아키텍처 | 시스템의 구성 요소와 관계를 정의한 구조 |
| SRS | 코딩 전에 무엇을 만들지 정의한 요구사항 명세서 |
| 관심사 분리 | 각 계층이 자신의 역할만 담당하도록 나누는 원칙 |