Search
*️⃣

(Basic Web Service Structure) & FastAPI

Category
BlogPost
Venue
Backbone
Text
PPT

Web Service Structure

A. 클라이언트 사이드 (Client-Side)
Web Browser/Client: 사용자가 직접 상호작용하는 인터페이스
DNS: 도메인 이름을 IP 주소로 변환하는 시스템
HTML 내부: DOM(Document Object Model) 구조로 페이지 구성
B. 네트워크 통신 계층
Internet: 클라이언트와 서버를 연결하는 네트워크 인프라
TCP/IP: 데이터 전송 프로토콜
HTTP: 웹 통신 프로토콜
C. 서버 사이드 (Server-Side)
Web Server: 클라이언트 요청 처리
HDD: 데이터 저장소
HTML/CSS/기타 파일들: 웹 페이지 구성 요소
1.
웹 서비스의 작동 방식:
A. 기본 GET 요청 흐름
1.
사용자가 브라우저에서 URL 입력
2.
DNS(Domain Name System)를 통해 도메인을 IP로 변환
3.
HTTP GET 요청이 서버로 전송
4.
서버는 요청된 리소스(HTML + CSS + 기타)를 응답
5.
브라우저는 받은 데이터를 DOM으로 파싱하여 화면 렌더링
B. POST 요청 흐름 (예: 폼 제출)
1.
사용자가 폼에서 "Click" 이벤트 발생
2.
HTTP POST 요청이 서버로 전송
3.
서버는 요청을 처리하고 적절한 응답 반환
4.
핵심 용어 및 개념 설명:
HTTP (HyperText Transfer Protocol)
GET: 리소스 요청 메소드
POST: 데이터 제출 메소드
Request/Response: 클라이언트-서버 간 통신 방식
DOM (Document Object Model)
HTML 문서의 프로그래밍 인터페이스
동적 페이지 조작을 위한 구조화된 표현
TCP/IP
인터넷 통신의 기본 프로토콜
데이터 패킷의 안정적인 전송 보장

FastAPI

#### What is FastAPI ?
Python 기반의 현대적이고 빠른 웹 프레임워크
비동기 처리를 지원하는 ASGI 서버 기반
#### 특징
자동 API 문서화 (OpenAPI/Swagger)
Python 타입 힌트 기반의 데이터 검증
비동기 처리 지원
높은 성능과 빠른 개발 속도
#### 장점
빠른 실행 속도 (Node.js, Go와 비견됨)
직관적인 코드 작성
자동화된 데이터 검증
풍부한 문서화 기능
#### 단점
학습 리소스가 Django나 Flask에 비해 적음
#### Toy Project/Code
######## Structure
. ├── main.py ├── static │ ├── form.html │ ├── form.js │ ├── pics.png │ ├── profile.jpg │ └── style.css └── templates └── intro.html
Python
복사
######## main.py
from fastapi import FastAPI, Request # FastAPI: 웹 프레임워크 클래스로, ASGI 서버를 구현하는 핵심 클래스 # Request: HTTP 요청 객체를 처리하는 클래스, 클라이언트의 요청 정보를 담음 from fastapi.responses import FileResponse # FileResponse: 파일을 HTTP 응답으로 보내는 클래스 # 정적 파일(HTML, 이미지 등)을 클라이언트에게 전송할 때 사용 from fastapi.staticfiles import StaticFiles # StaticFiles: 정적 파일(CSS, JavaScript, 이미지 등)을 서빙하기 위한 클래스 # 웹 서버가 변경 없이 그대로 제공하는 파일들을 관리 from fastapi.templating import Jinja2Templates # Jinja2Templates: Python의 템플릿 엔진 # HTML 파일에 동적 데이터를 삽입할 수 있게 해주는 기능 제공 from pydantic import BaseModel # BaseModel: 데이터 검증과 설정을 위한 Pydantic의 기본 모델 클래스 from typing import List # FastAPI 인스턴스 생성 app = FastAPI() # 정적 파일 디렉토리 설정 (/static 경로로 접근 가능) app.mount("/static", StaticFiles(directory="static"), name="static") # /static : 웹 브라우저에서 파일을 요청할 때 사용할 경로 # StaticFiles(directory="static"): "static"이라는 실제 폴더와 연결하라는 설정 # > 웹에서 "/static/style.css"로 요청이 오면 → 실제 "static/style.css" 파일을 찾아 제공 # name="static": 템플릿에서 정적 파일 경로를 동적으로 생성할 때 사용하는 식별자 # > url_for('static', ...) 처럼 사용할 때 'static'이라는 이름으로 참조 # Jinja2 템플릿 엔진 설정 (templates 디렉토리 사용) templates = Jinja2Templates(directory="templates") # Profile 데이터 모델 정의 class Profile(BaseModel): name: str title: str skills: List[str] # 루트 경로(/) GET 요청 처리 @app.get("/") def root(): return FileResponse("static/form.html") # 루트 경로(/) POST 요청 처리 @app.post("/") async def create_profile(request: Request, profile: Profile): return templates.TemplateResponse( "intro.html", { "request": request, "name": profile.name, "title": profile.title, "skills": profile.skills } )
Python
복사
######## 실제 Post에서 데이터의 흐름
1.
클라이언트 -> 서버: POST / 요청
// form.js에서 const response = await fetch('/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) });
Python
복사
2.
서버 -> 클라이언트: intro.html 응답
# main.py에서 @app.post("/") async def create_profile(request: Request, profile: Profile): return templates.TemplateResponse("intro.html", {...})
Python
복사
3.
클라이언트(브라우저): HTML 반환된거 받고 파싱시작 (아래 코드는 html 교체과정)
// form.js에서 응답을 받아 HTML을 교체 if (response.ok) { const html = await response.text(); document.documentElement.innerHTML = html; }
Python
복사
4.
클라이언트(브라우저): intro.html의 리소스 태그들 발견 (랜더링을 위해서 추가 데이터가 필요한 상황)
<link rel="stylesheet" href="/static/style.css"> <img src="/static/pics.png" alt="프로필 이미지">
Python
복사
5.
클라이언트 -> 서버: 각 리소스 요청
CSS 파일을 위한 GET /static/style.css 요청
이미지를 위한 GET /static/pics.png 요청
6.
서버: mount 설정으로 리소스 응답
# main.py의 이 설정으로 static 폴더의 파일들이 자동으로 제공됨 app.mount("/static", StaticFiles(directory="static"), name="static")
Python
복사
→ 구체적으로 클라이언트가 ‘GET /static/style.css’를 날려서 서버에 도착하면,
"아, URL이 /static으로 시작하네? → "그러면 이건 mount로 설정한 정적 파일 요청이구나" →"static 폴더에서 style.css를 찾아서 보내줘야지"의 논리적 흐름을 탐
이렇게 함으로써:
1.
각 정적 파일마다 별도의 라우트 함수를 만들 필요가 없어짐
@app.get("/static/style.css") def get_css(): return FileResponse("static/style.css") @app.get("/static/form.js") def get_js(): return FileResponse("static/form.js") @app.get("/static/pics.png") def get_image(): return FileResponse("static/pics.png")
Python
복사
2.
파일 시스템의 보안을 유지하면서도 필요한 파일들을 제공할 수 있음

References