콘텐츠로 이동

웹 서비스 설계와 아키텍처

우리가 만들 것은 무엇인가?

앞서 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 코딩 전에 무엇을 만들지 정의한 요구사항 명세서
관심사 분리 각 계층이 자신의 역할만 담당하도록 나누는 원칙