Next.js 앱에서 Passport, JWT, DDD를 사용한 로그인 구현
Source: Dev.to
Introduction
저는 원래 로그인 기능이 필요한 Next.js 애플리케이션을 만들었습니다. 이를 제대로 구현하기 위해 Passport(오랫동안 검증된 인증 라이브러리)를 선택하고 인증된 신원을 나타내는 보안 토큰으로 JWT를 사용했습니다. 지금까지는 꽤 표준적인 접근 방식입니다.
Architecture Overview
애플리케이션이 Domain‑Driven Design (DDD) 원칙을 따르길 원했기 때문에 시스템을 명시적으로 세 부분으로 나누었습니다:
Backend
- 데이터 영속성과 비즈니스 규칙 담당
- (API / GraphQL, 사용자 모델, 권한, 세션 유효성)
OAuth Express Server
- Passport를 완전히 소유하는 커스텀 Express 서버
- (전략, 로그인 오케스트레이션, 토큰 발급)
Frontend
- UI와 사용자 상호작용만 담당하는 Next.js 애플리케이션
Goals of the Separation
- 인증 로직을 프론트엔드 기술과 독립적으로 재사용 가능하게 함.
- 프론트엔드가 바뀔 수 있음.
- 백엔드가 바뀔 수 있음.
- OAuth를 로그인 로직을 다시 작성하거나 Passport를 특정 UI 프레임워크에 결합하지 않고도 프로젝트 간에 재사용 가능하게 함.
Next.js as a Bridge
Next.js는 서버와 브라우저 양쪽에서 실행되므로 강력한 단축키 역할을 합니다:
- Next.js가 OAuth 서버에 서버‑사이드로 호출합니다.
- 브라우저 외부에서 JWT를 받아옵니다.
- 그 JWT를 클라이언트에 전달하고 쿠키에 저장합니다.
개발자 입장에서는 우아하고 간단하게 느껴집니다. 하지만 아키텍처적으로는 미묘한 변화가 발생합니다: 프론트엔드가 이제 인증 저장에 참여하게 되는 것입니다. Passport는 다른 곳에 존재하지만, Next.js는 다음 이유로 신뢰 경계의 일부가 됩니다:
- 서버‑사이드에서 JWT를 수신
- 브라우저에 어떻게 영속시킬지 결정
Next.js가 서버‑사이드와 클라이언트‑사이드 모두에서 코드를 실행할 수 있는 능력은 인증 흐름을 구현하기에 적합합니다. 이 아키텍처에서는 Next.js가 서버에서 JWT를 안전하게 받아 브라우저 쿠키에 저장하는 단일 실행 경로를 가질 수 있습니다.
Benefits of Applying DDD
- 인증 로직이 프론트엔드 외부에 존재하므로 단일 프레임워크 안에 파묻히지 않음.
- 책임이 명확하고 경계가 분명함.
- 프론트엔드는 인증 세부 사항에 결합되지 않은 채 Next.js의 기능을 계속 활용할 수 있음.
핵심 요점은 로그인 기능이 결과물의 일부에 불과하다는 것입니다. 관심사를 분리함으로써 세 구성 요소 중 두 개를 다른 프로젝트에서도 그대로 재사용할 수 있게 됩니다.
Repository
이 아키텍처를 실제로 살펴보고 싶다면, 이 글에서 설명한 OAuth 컴포넌트를 공개 저장소에서 확인할 수 있습니다:
👉
저장소에는 위에서 설명한 대로 Passport 구현과 JWT 발급을 담당하는 독립형 OAuth Express 서버가 포함되어 있습니다. 프론트엔드 프레임워크와 무관하게 프로젝트 간에 재사용하도록 설계되었습니다.