Middleware란 무엇인가?
미들웨어는 서로 다른 애플리케이션이 서로 통신하는 데 사용되는 소프트웨어다.
미들웨어는 더욱 빠르게 혁신할 수 있도록 애플리케이션을 지능적이고 효율적으로 연결하는 기능을 제공한다.
단일 시스템에 원활하게 통합할 수 있도록 다양한 기술, 도구, 데이터베이스 간에 다리 역할을 한다. 예를 들어 Windows 프론트엔드 애플리케이션은 Linux 백엔드 서버에서 데이터를 송수신하지만, 애플리케이션 사용자는 그 차이를 인식하지 못한다.
출처: aws
Middleware가 중요한 이유는?
미들웨어는 새 애플리케이션과 레거시 시스템 사이를 잇는 다리 역할로 시작했다가 1980년대에 인기를 얻게 되었다. 개발자는 처음에 미들웨어를 사용하여 초기 코드를 다시 쓰지 않고도 새 프로그램을 초기 시스템과 통합하였다. 미들웨어는 분산 시스템의 중요한 통신 및 데이터 관리 도구가 되었다.
개발자는 미들웨어를 사용해 애플리케이션 개발을 지원하고 디자인 프로세스를 단순화한다. 이렇게 하면 서로 다른 소프트웨어 구성 요소 사이를 연결하지 않고 자유롭게 비즈니스 로직 및 기능에 중점을 둘 수 있다. 미들웨어가 없으면 개발자는 애플리케이션에 연결된 각 소프트웨어 구성 요소의 데이터 교환 모듈을 구축해야 한다. 이 구축 작업은 상당히 어렵다.
Middleware의 사용 사례는?
게임 개발
게임 개발자는 미들웨어를 게임 엔진으로 사용한다. 게임이 작동하기 위해서는 통신 시스템과 함께 소프트웨어가 다양한 이미지, 오디오 및 비디오 서버와 통신해야 한다.
게임 엔진은 이러한 통신을 원활하게 하고 게임 개발의 효율성을 높인다.
소프트웨어 개발
소프트웨어 개발자는 미들웨어를 사용하여 서로 다른 소프트웨어 구성 요소를 다른 애플리케이션에 통합한다. 미들웨어는 표준 API를 제공해 구성 요소에서 필요한 데이터 입력 및 출력을 관리한다.
Middleware Architecture란 무엇인가?
미들웨어 소프트웨어 아키텍처는 통신을 통해 데이터 파이프라인을 생성하는 여러 개의 구성 요소로 이루어져 있다. 데이터는 미들웨어를 통해 하나의 연결된 애플리케이션에서 다른 애플리케이션으로 이동한다.
관리콘솔
관리 콘솔은 소프트웨어 개발자에게 미들웨어 시스템의 활동, 소프트웨어 규칙 및 구성에 대한 개요를 제공한다.
클라이언트 인터페이스
클라이언트 인터페이스는 애플리케이션과 통신하는 미들웨어 소프트웨어에서 외부에 표시되는 부분이다. 개발자는 클라이언트 인터페이스가 제공하는 기능을 사용하여 다른 애플리케이션, 데이터베이스와 상호 작용한다.
미들웨어 내부 인터페이스
미들웨어 내부 인터페이스는 여러 구성 요소를 하나로 묶는 소프트웨어 연결 역할을 한다. 미들웨어 구성 요소는 내부 인터페이스를 사용하여 자체 프로토콜과 결속되어 기능한다.
플랫폼 인터페이스
플랫폼 인터페이스는 미들웨어 프로그램이 다양한 플랫폼과 호환되는지 확인한다. 여기에는 서로 다른 유형의 운영 체제와 함께 작동하는 소프트웨어 구성 요소가 포함된다.
이외에 세션 관리자, 데이터베이스 관리자, 런타임 모니터가 있다.
미들웨어는 어떻게 작동하나요?
미들웨어는 구성 요소 간의 기본 통신 프로세스를 담당한다. 즉 프론트엔드 애플리케이션은 미들웨어와만 통신하므로 다른 백엔드 소프트웨어 구성 요소의 언어를 배울 필요가 없다.

미들웨어를 여러 개 등록하면 스택(Stack) 구조로 쌓인다. 나중에 등록한 미들웨어가 가장 바깥쪽에 위치한다.

미들웨어의 예
예를 들어 웹 서버는 웹 사이트를 백엔드 데이터베이스에 연결하는 미들웨어이다. 웹 사이트에서 양식을 제출하면 컴퓨터는 XML 또는 JSON 형식의 요청을 웹 서버에 전송한다. 그럼 웹 서버는 해당 요청에 기반하여 비즈니스 로직을 실행하고 데이터베이스에서 정보를 검색하거나 서로 다른 프로토콜을 사용하여 다른 마이크로서비스와 통신한다.
다른 미들웨어 기능
- 웹 사이트가 민감한 정보를 벡엔드 애플리케이션에 안전하게 전송할 수 있도록 분산 애플리케이션 간의 안전한 통신 채널을 제공한다.
- 트래픽 흐름을 관리하여 특정 애플리케이션 또는 파일 서버에 과도한 트래픽이 전달되지 않게 한다..
- 요청에 대한 응답을 자동화하고 사용자 지정합니다. 예를 들어 미들웨어는 결과를 분류하고 필터링한 다음 프런트엔드 애플리케이션에 전송한다.
미들웨어 구현의 기본 구조
FastAPI에서 미들웨어를 만드는 가장 일반적인 방법은 @app.middleware(”http”) 데코레이터를 사용하는 것이다. 이 함수는 크게 세 단계로 작동한다.
- 요청 가로채기(Request Intercept): 클라이언트의 요청이 API 함수(엔드포인트)에 도달하기 전에 공통 로직(로깅, 인증 등)을 실행한다.
- 다음 단계로 전달(
call_next): 요청을 다음 미들웨어나 실제 API 함수로 넘긴다. - 응답 가로채기(Response Intercept): API 함수가 만든 응답이 클라이언트에게 나가기 전에 추가 작업(헤더 추가, 실행 시간 계산 등)을 수행한다.
FastAPI에서 모든 요청에 공통 로직을 적용하려면 미들웨어를 사용하여 요청 파이프라인의 입구와 출구를 제어한다.
미들웨어 vs 의존성 주입
| 구분 | 미들웨어 (Middleware) | 의존성 주입 (Depends) |
|---|---|---|
| 적용 범위 | 전체. 모든 API에 무조건 적용됨 | 선택. 특정 API 함수에만 적용 가능 |
| 주요 용도 | 로깅, CORS 설정, 전체 보안 | DB 연결 세션 관리, 특정 권한 체크 |
| 장점 | 한 곳에서 일괄 관리가 가능함 | 유연하게 필요한 곳에만 꽂아 쓸 수 있음 |
CORS 미들웨어가 필요한 이유 “보안상의 출입 통제”
웹 브라우저는 보안을 위해 “A라는 사이트에서 가져온 스크립트가 B라는 사이트의 데이터를 함부로 가져오지 못하게” 막는다. 이를 동일 출처 정책(SOP)라고 한다.
하지만 현대적인 웹 서비스는 보통 프론트와 백엔드의 “도메인/프로토콜/포트의 조합” 이 서로 다르다. 이때 브라우저는 백엔드 서버에 “이 다른 출처의 요청을 허용해도 돼?”라고 물어본다.
그럼 CORS 미들웨어는 “이 사이트는 안전하니 허용해.”라고 답해주는 역할을 한다.
CORS 미들웨어를 적절히 설정하지 않으면 다음과 같은 문제가 발생한다.
- 브라우저의 요청 차단: 서버 자체는 정상적으로 작동하고 데이터를 보낼 준비가 되어 있더라도 브라우저가 응답을 가로채 사용자에게 전달하지 않는다.
- CORS Error 발생: 개발자 도구 콘솔에
Access-Control-Allow-Origin헤더가 없다는 빨간색 에러 메시지가 출력된다. - 서비스 마비: 프론트엔드와 백엔드가 서로 통신할 수 없게 되어, 로그인이나 데이터 조회 등 웹 앱의 핵심 기능이 작동하지 않는다.
FastAPI 요청-응답 생명주기
1. 클라이언트 요청 단계
클라이언트가 보내는 HTTP 요청
- 예를 들어 사용자가 POST 요청을 보내면 이 요청은 TCP 소켓을 통해 ASGI 서버로 전달된다.
2. ASGI 서버의 요청 파싱 단계
(1) TCP 소켓을 통해 수신한 바이트 스트림을 HTTP 프로토콜에 맞게 파싱
ASGI 서버는 클라이언트의 요청 바이트 스트림을 해석하여 scope 딕셔너리를 생성한다.
scope = {
"type": "http",
"http_version": "1.1",
"method": "POST",
"scheme": "http",
"path": "/generation/chatgpt",
"raw_path": b"/generation/chatgpt",
"query_string": b"",
"headers": [
[b"host", b"example.com"],
[b"content-type", b"application/json"],
[b"content-length", b"123"],
# 기타 헤더들...
],
"client": ("127.0.0.1", 54321),
"server": ("example.com", 80),
}
이 scope에는 요청 경로, HTTP 메서드, 헤더 등의 정보가 담긴다.
(2) ASGI 서버가 FastAPI 인스턴스를 호출
ASGI 서버는 위의 scope와 함께, receive(수신) 및 send (송신) 콜러블을 인자로 FastAPI 애플리케이션을 호출한다.
3. FastAPI 애플리케이션 내부 처리 단계
(1) Request 객체 생성 및 미들웨어 체인
클라이언트의 요청이 서버에 도착하면, FastAPI(ASGI)는 원본 데이터를 가공해 파이썬이 이해할 수 있는 Request 객체를 만든다. 이후 메인 로직에 가기 전에 미들웨어 체인을 통과한다.
- 비유 (공항 보안 검색대): 비행기 티켓(요청)을 들고 입국장에 들어서면, 미들웨어(보안 요원)들이 줄지어 서 있습니다.
- 첫 번째 요원은 CORS 검사를 합니다 (우리 국가와 협약된 지역에서 왔는지 확인).
- 두 번째 요원은 Logging을 합니다 (누가 몇 시에 들어왔는지 장부에 기록).
- 세 번째 요원은 인증/인가를 확인합니다 (위조 여권은 아닌지 확인).
- 이들은 '체인'처럼 연결되어 있어, 한 명이라도 "통과 불가"를 외치면 다음 단계로 가지 못하고 바로 퇴장(401, 403 에러)당합니다.
(2) 라우터와 엔드포인트 매칭
FastAPI는 미리 등록된 주소 목록을 보고, 요청된 URL과 HTTP 메서드가 일치하는 엔드포인트 핸들러(담당 함수)를 찾아 연결해준다.
- 비유 (공항 안내 데스크): 승객이 "저는
/gpt-generation도시로 가고 싶어요"라고 말하면, 안내 데스크(라우터)는 자신의 노선도(라우팅 테이블)를 확인합니다.
(3) 요청 데이터의 모델 파싱
클라이언트가 보낸 JSON 데이터를 서버 내부 로직에서 사용하기 위해 파이썬 객체로 변환하고 검증한다.
- 역직렬화 : 네트워크를 통해 전송된 Byte/String 형태의 JSON 데이터를 파이썬의 딕셔너리나 오브젝트 형태로 변환한다.
- 스키마 검증: FastAPI는 Pydantic 라이브러리를 사용하여 정의된 모델 클래스와 들어온 데이터가 일치하는지 전수 조사한다.
- 타입 캐스팅: JSON은 타입을 엄격히 구분하지 않지만 Pydantic은 유동적으로 형변환을 한다.
- 결과: 검증에 실패하면 HTTP 422 에러 응답을 즉시 반환하며 성공하면 비즈니스 로직 함수에 깨끗하게 정제된 파이썬 객체가 인자로 전달된다.
(4) 서비스 로직 실행
시간이 오래 걸리는 I/O 작업을 이벤트 루프에서 분리하여, 서버 한 대가 동시에 많은 접속자를 처리할 수 있도록 리소스를 분배한다.
4. 응답 객체 처리 단계
(1) 엔드포인트 반환값 처리
엔드포인트 핸들러는 위에서 생성된 객체를 반환하고 FastAPI는 이를 JSON 직렬화하여 응답 객체로 변환한다.
(2) 미들웨어 후처리
응답 객체는 다시 미들웨어 체인을 거치며 여기서 추가적인 후처리(헤더 수정, 데이터 압출 등)를 수행할 수 있다.
(3) ASGI 이벤트 메시지 생성
FastAPI(Starlette)는 응답 객체를 ASGI 이벤트 메시지로 변환한다.
5. 최종 응답 전송 단계
(1) ASGI 서버의 응답 직렬화
ASGI 서버는 이벤트 메시지를 HTTP 프로토콜에 맞는 최종 바이트 스트림으로 직렬화한다.
(2) TCP 소켓을 통한 응답 전송
이 최종 바이트 스트림은 TCP 소켓을 통해 클라이언트로 전송되어 브라우저나 클라이언트 애플리케이션에서 HTTP 응답으로 처리된다.