미들웨어(요청 수명 주기)란?

업데이트: 2026년 10월

미들웨어는 라우트 로직이 실행되기 전에 요청과 응답을 검사하거나 수정하는, 요청 파이프라인 안의 함수입니다. 이 단어에는 두 가지 의미가 있습니다. 하나는 오래된 엔터프라이즈 의미(애플리케이션 사이에 놓이는 메시지 브로커와 통합 버스)이고, 다른 하나는 이 글이 다루는 웹 프레임워크의 의미, 즉 한 애플리케이션 안에서 모든 요청이 순서대로 거쳐 가는 함수입니다. Express는 이 모델을 분명하게 설명합니다. 앱은 “본질적으로 일련의 미들웨어 함수 호출”이며, 그 호출의 순서가 말 그대로 프로그램입니다.

핵심 요약

질문답변
계약검사/수정 → 응답(단락) 또는 next() 호출
형태양파 구조: 요청은 스택을 따라 내려가고, 응답은 거슬러 올라옴
법칙등록 순서 = 실행 순서 – 미들웨어 버그는 대부분 순서 버그
표준 스택헤더 → CORS → 파싱 → 로깅 → 인증 → 인가 → 제한 → 라우트 → 404 → 오류
vs. 게이트웨이미들웨어는 한 앱 안에서 실행되고, 게이트웨이는 여러 앱 앞에 섬

순서대로 쌓은 스택

// JavaScript / Node.js — Express + Parse Server
// Middleware: functions the request flows through, in registration order
const app = express();
app.use(helmet());                       // 1 · security headers
app.use(cors(corsOptions));              // 2 · CORS before anything that fails
app.use(express.json({ limit: '1mb' })); // 3 · body parsing, bounded

// Parse Server IS middleware — a whole backend mounted into the stack
app.use('/parse', new ParseServer(config).app);

app.use(notFoundHandler);                // 404 — after all routes
app.use(errorHandler);                   // error handler LAST (4 args)

각 위치에는 이유가 있습니다. 보안 헤더가 가장 먼저입니다(오류를 포함한 모든 응답에 붙어야 합니다). CORS는 실패할 수 있는 모든 것보다 앞에 둡니다(그렇지 않으면 브라우저가 실제 오류를 가립니다). 본문 파싱은 크기를 제한하고 라우트보다 앞에 둡니다(그렇지 않으면 req.body가 undefined입니다). 인증은 인가보다 먼저입니다(아무도 아닌 대상에 대해 검사한 권한은 누구에게나 허용된 권한입니다). 속도 제한은 비용이 큰 작업보다 앞에 둡니다(데이터베이스 쿼리 뒤에 있는 제한기는 아무것도 보호하지 못합니다). 404는 모든 라우트 뒤에, 오류 핸들러는 맨 마지막에 둡니다.

양파 구조, 제대로 그리기

요청이 내려가고 응답이 올라오는 미들웨어 양파 구조요청은 등록 순서대로 각 미들웨어 계층을 거쳐 안쪽으로 들어가 중심에 있는 라우트 핸들러에 도달하고, 응답은 같은 계층을 역순으로 거쳐 바깥으로 돌아옵니다. 따라서 각 미들웨어는 들어갈 때 한 번, 나올 때 한 번, 두 번 동작할 수 있습니다. 어떤 계층은 단락하여 안쪽 계층이 실행되기 전에 응답을 보낼 수 있습니다.

단락:
401, 안쪽은 실행되지 않음

요청

헤더 / CORS

인증

속도 제한

라우트 핸들러
(중심)

속도 제한
(응답 경로)

인증
(시간 측정, 감사)

헤더 기록

응답

요청은 등록 순서대로 각 미들웨어 계층을 거쳐 안쪽으로 들어가 중심에 있는 라우트 핸들러에 도달하고, 응답은 같은 계층을 역순으로 거쳐 바깥으로 돌아옵니다. 따라서 각 미들웨어는 들어갈 때 한 번, 나올 때 한 번, 두 번 동작할 수 있습니다. 어떤 계층은 단락하여 안쪽 계층이 실행되기 전에 응답을 보낼 수 있습니다.

대부분의 설명에서 빠지는 절반이 있습니다. 파이프라인은 양방향으로 실행됩니다. Django 문서는 이를 양파로 그립니다. 각 미들웨어는 중심에 있는 뷰를 감싸는 계층이며, next() 호출 뒤(또는 get_response 뒤)의 코드는 응답이 바깥으로 돌아가는 길에 역순으로 실행됩니다. 응답 시간을 측정하고, 헤더를 기록하고, 실제로 일어난 일을 로그로 남기는 곳이 바로 여기입니다. 단락(short-circuit)하는 계층은 핸들러만 건너뛰는 것이 아니라 안쪽 모든 계층의 양쪽 절반을 건너뜁니다. 인증 관문이 존재하는 이유가 바로 이 보장입니다.

실제로 배포되는 순서 버그

일반적인 조언은 “순서가 중요하다”이지만, 구체적인 버그가 더 많은 것을 알려 줍니다. 인증보다 앞선 인가: 권한 검사가 익명 주체를 대상으로 실행됩니다. 401/403이 간헐적으로 발생하고, 예외는 어디에도 없으며, 디버깅에 몇 시간이 걸립니다. 라우트 뒤의 본문 파서: 모든 핸들러가 req.body === undefined를 보고 클라이언트를 탓합니다. CORS보다 앞선 인증: 401 응답 자체에 CORS 헤더가 없어서 브라우저가 이를 차단하므로, 프론트엔드는 실제 오류 대신 네트워크 오류를 봅니다. 인증보다 앞선 정적 파일: 비공개 파일이 인증되지 않은 사용자에게 아무렇지 않게 제공됩니다. 맨 끝이 아닌 오류 핸들러: 스택에서 그보다 뒤에서 던져진 오류는 결코 그곳에 도달하지 않습니다. 이 버그들은 모두 정상 경로의 스모크 테스트를 통과합니다. 순서 버그는 그대로 배포되는 종류의 버그입니다.

단락: next()를 호출하지 않는 것이 핵심일 때

계약에는 합법적인 출구가 두 개 있습니다. 제어권을 넘기거나, 주기를 끝내는 것입니다. 일찍 끝내는 것은 미들웨어의 실패가 아니라 역할의 절반입니다. 인증 관문의 401, 제한기의 429, 캐시 적중, 리디렉션, 그 자리에서 응답하는 CORS 프리플라이트가 그렇습니다. 두 출구를 모두 정직하게 유지하는 규칙은 이것입니다. 언제나 정확히 하나만 합니다. 응답하거나, next()를 호출하거나. 둘 다 하지 않으면 요청이 영원히 멈추고, 둘 다 하면 헤더가 이미 전송되었다는 오류가 발생해 하류의 모두를 혼란에 빠뜨립니다.

모든 프레임워크에 있는 같은 개념

프레임워크미들웨어의 형태제어권 넘기기나가는 길
Express(req, res, next) => {}next()next() 뒤의 코드 (주의 필요)
Djangoget_response를 감싸는 callableget_response(request)호출 뒤의 코드 – 양파 구조
Rack / Railscall(env)를 가진 객체@app.call(env)호출이 반환된 뒤
Koa / Honoasync (ctx, next) => {}await next()await 뒤 – 일급 기능

하나의 모델, 네 가지 억양입니다. 오류 경로는 프레임워크마다 고유한 관례가 있습니다. Express에서는 인자 네 개짜리 (err, req, res, next) 시그니처 자체가 등록 메커니즘입니다. 그래서 “쓰이지 않는” 파라미터를 지우면 오류 핸들러가 조용히 결코 실행되지 않는 일반 미들웨어로 바뀝니다.

미들웨어 vs. 게이트웨이 vs. 훅

Criterion미들웨어API 게이트웨이데이터 훅
실행 위치한 앱의 프로세스 안여러 앱의 앞데이터 작업의 앞뒤
단위요청별요청별, 서비스 전반save/delete/find별
담당이 앱의 파이프라인라우팅, 엣지 인증, 전역 제한검증, 데이터 반응
설정 방식코드로, 순서대로인프라 설정클래스별 등록

세 개의 가로채기 계층이 하나의 중첩 구조를 이룹니다. 게이트웨이는 서비스 전체의 앞에 서고, 미들웨어는 각 앱의 관문을 운영하며, 훅은 요청이 데이터가 되는 지점에서 실행됩니다. 관심사는 그것을 결정할 수 있는 가장 바깥 계층에 둡니다. 전역 속도 제한은 게이트웨이에, 세션 인증은 미들웨어에, “이 쓰기가 유효한가”는 훅에 둡니다.

일반적인 사용 사례

  • 인증과 세션 처리 – 신원을 한 번, 일찍 확인해 그 뒤의 모든 처리에 씁니다.
  • 공통 위생 처리 – CORS, 보안 헤더, 압축, 요청 ID.
  • 입력 규율 – 크기 제한을 둔 본문 파싱, Content-Type 강제, 검증.
  • 관측 가능성 – 양파 구조의 복귀 경로를 이용해 파이프라인 전체를 감싸는 로깅과 시간 측정.
  • 트래픽 보호 – 비용이 발생하기 전에 단락하는 속도 제한과 남용 차단 관문.

어느 계층에 둘까? 결정 매트릭스

관심사계층
운영하는 모든 앱에 적용게이트웨이
이 앱의 모든 요청에 적용미들웨어, 위치를 의도적으로 정해서
특정 라우트에 적용라우터 수준 미들웨어
데이터를 쓰거나 읽을 때 적용beforeSave / beforeFind 훅
커스텀 비즈니스 작업파이프라인 꼼수가 아닌 함수
오류 형태 지정오류 미들웨어 – 맨 끝, 인자 네 개, 예외 없음

한계와 트레이드오프

  • 순서는 문제가 생기기 전까지 보이지 않습니다. 스택은 위에서 아래로 읽히지만, 실패는 엉뚱한 곳을 가리키는 방식으로 일어납니다. 미들웨어 등록은 리뷰를 거치는 핵심 코드로 다뤄야 합니다.
  • 모든 계층은 모든 요청에 비용을 부과합니다. 2ms짜리 미들웨어 열 개는 모든 응답에 20ms를 더합니다. 쿼리를 측정하듯 스택도 측정해야 합니다.
  • 전역 상태는 함정입니다. 미들웨어는 여러 요청에 걸쳐 동시에 실행되므로, 공유되는 가변 상태는 무엇이든 경쟁 조건이 됩니다. 요청별 데이터는 요청 객체에만 붙여야 합니다.
  • 파이프라인은 제어 흐름을 숨깁니다. 세 단계 안쪽에서 단락하는 계층이 라우트가 “절대 실행되지 않는” 이유일 수 있습니다. 디버깅의 첫수는 언제나 스택을 순서대로 출력해 보는 것입니다.
  • 모든 것이 파이프라인의 관심사는 아닙니다. 미들웨어에 슬쩍 넣은 비즈니스 로직은 모든 라우트를 그것에 결합시킵니다. 파이프라인은 핵심 로직이 아니라 횡단 관심사(cross-cutting concern)를 위한 것입니다.

Back4app에서의 미들웨어

Back4app은 관리형 데이터베이스, 자동 생성되는 REST 및 GraphQL API, 인증, 파일 스토리지, Cloud Code 서버리스 함수를 결합한 오픈소스 Backend as a Service(BaaS) 플랫폼입니다. 이 관계는 유난히 문자 그대로입니다. Back4app의 서버 자체가 Express 미들웨어입니다. JavaScript 탭은 이 서버가 app.use('/parse', …)로 표준 스택에 마운트되는 모습을 보여 줍니다. 그리고 플랫폼은 모든 요청에 대해 표준 관문을 실행합니다. 보안 헤더, CORS, 크기를 제한한 파싱, 키 검사, 세션 인증, 속도 제한이 올바른 순서로, 인프라로서 유지됩니다. 요청별 커스텀 로직은 직접 만든 파이프라인 코드가 아니라 결정 매트릭스가 가리키는 곳에 둡니다. 데이터와 맞닿은 규칙에는 beforeSave/beforeFind 트리거를, 작업에는 Cloud Function을 씁니다. 각각 요청의 사용자 컨텍스트가 연결되어 있으며, 이것이 커스텀 미들웨어가 알고 싶어 했던 것의 대부분입니다.

자주 묻는 질문

미들웨어를 쉽게 설명하면 무엇입니까?

들어오는 요청과 라우트 로직 사이의 경로에 자리 잡고, 지나가는 모든 요청을 처리하는 함수입니다. 탑승구 앞의 공항 보안 검색대와 비슷합니다. 각 미들웨어는 요청을 검사하거나 수정한 뒤 다음으로 넘기거나 그 자리에서 멈춰 세웁니다.

흔한 미들웨어의 예로는 무엇이 있습니까?

일반적인 스택은 보안 헤더, CORS, 크기 제한을 둔 본문 파싱, 로깅, 인증, 인가, 속도 제한, 정적 파일 제공, 그리고 맨 끝의 404 핸들러와 오류 핸들러입니다. 웹 앱에서 여러 곳에 걸치는 관심사는 거의 모두 미들웨어입니다.

미들웨어 체인은 어떻게 동작합니까?

각 함수는 응답을 보내 주기를 끝내거나, next()를 호출해 다음 함수에 제어권을 넘깁니다. 프레임워크는 무언가가 응답할 때까지 등록 순서대로 스택을 따라갑니다. 고전적인 버그는 응답도 하지 않고 next()도 호출하지 않는 경우로, 요청이 영원히 멈춰 있게 됩니다.

미들웨어 순서가 중요합니까?

가장 흔한 버그 원인입니다. 인증보다 앞선 인가는 아무도 아닌 대상의 권한을 검사합니다. 라우트 뒤에 둔 본문 파서는 req.body를 undefined로 남깁니다. CORS보다 앞선 인증은 브라우저가 실제 오류를 가리게 만듭니다. 맨 끝이 아닌 곳에 둔 오류 핸들러는 아무것도 잡지 못합니다. 순서가 곧 프로그램입니다.

오류 처리 미들웨어란 무엇입니까?

프레임워크가 일반 체인 대신 오류를 보내는 미들웨어입니다. Express에서는 인자 네 개짜리 시그니처 (err, req, res, next)로 식별되며, 맨 마지막에 등록합니다. 던져진 오류와 next(err) 호출은 나머지를 모두 건너뛰고 이곳에 도착하므로, 위치는 타협할 수 없습니다.

미들웨어와 라우트 핸들러의 차이는 무엇입니까?

의도와 위치가 다릅니다. 미들웨어는 여러 라우트에 걸친 공통 관심사를 처리하고 보통 제어권을 넘깁니다. 라우트 핸들러는 응답을 만들어 내는 목적지입니다. 대부분의 프레임워크에서 둘은 구조적으로 똑같은 함수이며, 파이프라인이 그중 하나에서 끝날 뿐입니다.

미들웨어와 API 게이트웨이의 차이는 무엇입니까?

범위가 다릅니다. 미들웨어는 한 애플리케이션의 프로세스 안에서 요청마다 실행됩니다. 게이트웨이는 여러 애플리케이션 앞에 놓인 인프라로, 서비스 전반의 라우팅, 인증, 속도 제한을 처리합니다. 게이트웨이는 아키텍처 전체를 위한 미들웨어이며, 둘은 경쟁하지 않고 조합됩니다.

미들웨어가 next()를 호출하지 말아야 할 때는 언제입니까?

요청을 완전히 처리했을 때입니다. 401을 반환하는 인증 거부, 429를 반환하는 속도 제한기, 캐시 적중, 리디렉션, CORS 프리플라이트 응답이 그렇습니다. 단락은 기능입니다. 관문을 통과하지 못한 요청에 대해서는 관문 너머의 어떤 것도 실행되지 않는다는 보장입니다.

관련 용어

비교 대상

참고 자료

백엔드를 구축할 준비가 되셨나요?

몇 분 안에 Back4app에서 프로젝트를 시작하세요. 데이터베이스, 인증, API, Cloud Code가 포함되어 있으며 신용카드는 필요 없습니다.

작성 및 검수: Back4app Engineering, Back4app Engineering · 게시일 2026-10-31