핵심 요약 (Summary)
미들웨어(Middleware)는 클라이언트의 요청이 서버에서 처리되기 전에 가로채서 추가적인 작업을 수행하는 중간 처리 계층입니다. Next.js에서 미들웨어를 활용하면 페이지나 API가 실행되기 전에 인증 검사, 리다이렉트, 헤더 수정 같은 공통 로직을 한 곳에서 처리할 수 있습니다.
미들웨어란 무엇인가요? (Concept)
미들웨어라는 단어는 "중간(middle)"과 "소프트웨어(software)"의 합성어입니다. 말 그대로, 요청과 응답 사이에서 중간 역할을 하는 계층입니다.
사용자가 브라우저에서 특정 URL로 접근하면, 그 요청은 서버에 도달하기 전에 미들웨어를 먼저 통과합니다. 미들웨어는 이 요청을 보고 그대로 통과시킬지, 다른 곳으로 보낼지, 아니면 요청 자체를 변형할지를 결정합니다.
이 흐름을 단순하게 표현하면 다음과 같습니다.
클라이언트 요청 → 미들웨어 → 서버(페이지 또는 API) → 응답 → 클라이언트
미들웨어는 이 흐름의 가장 앞단에 위치하기 때문에, 모든 요청이 반드시 거쳐가는 관문 역할을 합니다.
왜 이런 개념이 필요한가요? (Why)
프론트엔드 애플리케이션이 복잡해질수록, 여러 페이지에서 공통으로 처리해야 하는 로직이 생깁니다. 대표적인 예가 인증입니다.
로그인하지 않은 사용자가 마이페이지나 대시보드에 접근하면, 해당 페이지로 보내는 것이 아니라 로그인 페이지로 보내야 합니다. 이 로직을 각 페이지마다 개별적으로 작성하면 코드가 중복되고, 하나를 수정할 때 나머지를 빠뜨리는 실수가 생깁니다.
미들웨어를 사용하면 이런 공통 로직을 단 한 곳에 모아둘 수 있습니다. 특정 경로에 대한 접근 요청이 들어올 때마다 미들웨어가 먼저 실행되어, 사용자의 상태를 확인하고 적절한 처리를 수행합니다.
Next.js 미들웨어의 동작 원리 (How It Works)
Next.js에서 미들웨어는 Edge Runtime이라는 환경에서 실행됩니다. Edge Runtime은 일반적인 Node.js 서버와 다르게, 사용자와 지리적으로 가장 가까운 서버에서 코드를 실행하는 방식입니다.
이 특성 덕분에 미들웨어는 매우 빠르게 응답할 수 있습니다. 전통적인 서버 처리를 기다릴 필요 없이, 요청이 들어오는 즉시 처리가 이루어집니다.
하지만 Edge Runtime은 Node.js의 모든 기능을 지원하지 않습니다. 파일 시스템 접근이나 특정 Node.js 전용 모듈은 사용할 수 없고, 사용할 수 있는 API가 Web API 기반으로 제한됩니다. 미들웨어에서 무거운 데이터베이스 조회나 복잡한 서버 로직을 처리하지 않아야 하는 이유가 여기에 있습니다.
미들웨어는 프로젝트 루트에 middleware.ts 파일 하나로 정의하며, matcher 설정을 통해 어떤 경로에서 실행할지 지정합니다.
미들웨어의 주요 사용 목적 (Use Cases)
1. 인증과 접근 제어
가장 대표적인 사용 목적입니다. 로그인 여부를 확인하고, 인증되지 않은 사용자를 로그인 페이지로 리다이렉트합니다. 쿠키나 토큰을 읽어서 유효성을 검사하는 로직이 여기에 들어갑니다.
2. 리다이렉트와 URL 정규화
/home으로 접근한 사용자를 /로 보내거나, 대문자가 포함된 URL을 소문자로 통일하는 처리를 미들웨어에서 수행할 수 있습니다. SEO 관점에서 URL을 일관되게 유지하는 데도 유용합니다.
3. 국제화(i18n) 처리
사용자의 브라우저 언어 설정이나 IP 주소를 분석해 적절한 언어의 페이지로 안내할 수 있습니다. 한국 사용자는 /ko/..., 영어권 사용자는 /en/...으로 자동 이동시키는 방식입니다.
4. 요청 헤더 수정
페이지나 API가 실행되기 전에 요청 헤더를 추가하거나 변경할 수 있습니다. 현재 접속한 URL 정보나 사용자 식별자를 헤더에 담아 서버 컴포넌트에서 읽어가도록 만들 수 있습니다.
5. A/B 테스트와 기능 플래그
특정 사용자 그룹에게는 A 버전 페이지를, 다른 그룹에게는 B 버전 페이지를 보여주는 실험을 미들웨어 단에서 처리할 수 있습니다. 페이지 코드를 건드리지 않고 URL 리라이트(rewrite)를 통해 구현합니다.
6. 봇 차단과 보안
특정 User-Agent나 IP 패턴을 가진 요청을 필터링하거나, 악성 요청에 대해 403 응답을 반환하는 기본적인 보안 처리를 미들웨어에서 수행할 수 있습니다.
리다이렉트(Redirect)와 리라이트(Rewrite)의 차이
미들웨어에서 자주 사용하는 두 가지 개념입니다.
**리다이렉트(Redirect)**는 사용자의 브라우저 주소창 URL이 실제로 바뀝니다. 브라우저가 새로운 URL로 다시 요청을 보내기 때문에, 사용자도 URL이 변경되었음을 확인할 수 있습니다.
**리라이트(Rewrite)**는 URL이 겉으로 보기에는 그대로지만, 내부적으로 다른 페이지를 렌더링합니다. 사용자는 /dashboard에 접속했다고 생각하지만, 실제로는 /dashboard/overview의 콘텐츠를 보여주는 방식입니다. A/B 테스트에서 유용하게 사용됩니다.
미들웨어를 사용할 때 주의할 점 (Caution)
미들웨어는 매우 강력한 도구지만, 잘못 사용하면 성능 문제와 예기치 않은 동작을 유발합니다.
첫째, 미들웨어는 매 요청마다 실행됩니다. 무거운 연산이나 외부 API 호출을 미들웨어에 넣으면 전체 응답 속도에 영향을 줍니다. 미들웨어는 가볍고 빠르게 실행될 수 있는 로직만 담아야 합니다.
둘째, 미들웨어는 Edge Runtime 제약을 받기 때문에 ORM이나 데이터베이스 클라이언트를 직접 사용할 수 없습니다. 인증 토큰 검증처럼 외부 의존성이 없는 로직을 처리하고, 복잡한 데이터 접근은 서버 컴포넌트나 API Route에서 처리하는 것이 올바른 역할 분리입니다.
셋째, matcher 설정 없이 모든 경로에 미들웨어를 적용하면 정적 파일(이미지, CSS 등)에도 미들웨어가 실행됩니다. matcher를 사용해 실제로 필요한 경로에만 미들웨어를 적용해야 합니다.
정리 (Conclusion)
미들웨어는 요청이 실제 페이지나 API에 도달하기 전에 실행되는 중간 처리 계층입니다. Next.js에서는 Edge Runtime 위에서 동작하며, 인증 검사, 리다이렉트, 헤더 수정, 국제화 처리 등 공통 로직을 한 곳에서 관리할 수 있게 해줍니다.
미들웨어를 잘 활용하면 각 페이지에 중복으로 작성하던 로직을 제거하고 코드를 훨씬 깔끔하게 유지할 수 있습니다. 단, Edge Runtime의 제약과 성능 특성을 이해하고, 가볍고 명확한 역할만 담도록 설계하는 것이 핵심입니다.