Payload에서 맞춤 인증

발행: (2025년 12월 13일 오후 12:51 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

Cover image for Custom auth in Payload

대부분의 PayloadCMS 인증 예제는 일반 이메일/비밀번호 또는 “장난감” OAuth 설정을 다루며, 다중 프론트엔드, 네이티브 앱, 서드파티 아이덴티티 제공자와 같은 실제 제약을 도입하면 바로 무너집니다.

팀은 프레임워크와 싸우게 되고, 세션 상태를 전혀 맞지 않는 곳에 전달하거나, 아직 세션이 없을 때 req.user에 의존하거나, 관리 인증을 애플리케이션 인증에 결합시켜 프로젝트가 성장함에 따라 이해하기 어려운 상황에 빠집니다.

실제로 인증은 헤드리스 스택에서 가장 빨리 노후되는 부분이며, 즉흥적으로 구현하면 가장 큰 문제를 일으킵니다. 또한 새벽 2시에 디버깅하고 싶지 않은 부분이기도 합니다. 그래서 Payload가 v3에서 명시적인 커스텀 전략으로 이동한 것이 큰 의미가 있습니다: 이는 제어권을 여러분에게 되돌려 주는 동시에, 인증을 일급 설계 관점으로 생각하도록 조용히 요구합니다.

Rethinking auth

마음가짐의 전환은 Payload를 “사용자를 로그인시키는 것”이 아니라 “이미 검증된 아이덴티티를 신뢰하는 것”으로 보는 것입니다. 여러분의 아이덴티티 제공자—Google이든, 전용 인증 서비스이든, 맞춤형 OAuth 서버이든—가 의식( ceremony )을 담당합니다: PKCE, 리다이렉트, 디바이스 플로우, 매직 링크 등 모든 과정. Payload의 역할은 훨씬 좁고 명확합니다; 요청에 포함된 검증 가능한 아이덴티티 증거(헤더, 토큰, 쿠키 등)를 받아 해당 사용자 문서와 매핑하고, 필요에 따라 사용자를 생성하거나 업데이트합니다.

이것이 바로 커스텀 인증 전략이 존재하는 이유입니다. 여러분은 들어오는 요청 컨텍스트를 받아 “이 요청이 나타내는 사용자는 누구인가(있는가)?” 라는 질문에 답해야 하는 함수를 구현합니다. 겉보기엔 간단해 보이지만, 이 계약에 전념하면 아키텍처가 자연스럽게 정리됩니다. 프론트엔드는 실제 OAuth 흐름을 담당하고, Payload는 명확하고 일관된 사용자 데이터를 기반으로 접근 규칙을 적용하는 역할을 맡게 됩니다.

Production

팀이 흔히 부딪히는 문제는 경계선입니다. 관리 사용자와 앱 사용자는 동일하지 않을 수 있습니다. 외부 통합은 일반 로그인 흐름을 우회하는 API 키나 서비스 계정이 필요합니다. 모바일 앱은 관리 UI와 전혀 연결되지 않는 인증 경로가 필요합니다. “관리자를 통해 로그인하고 끝내자”는 전략을 쓰면 라우트, 훅, 임시 미들웨어에 로직이 흩어지게 됩니다.

전략 중심의 접근 방식은 그 로직을 중앙집중화하도록 강제합니다. 하나의 전략은 OAuth 제공자에서 받은 서명된 토큰을 사용자 컬렉션에 매핑하고, 다른 전략은 내부 서비스 토큰을 처리하며, 또 다른 전략은 관리 전용 흐름에 전용될 수 있습니다. 이렇게 하면 테스트가 쉬워지고, 이해하기 쉬우며, 가장 중요한 점은 아이덴티티 요구사항이 변할 때(필연적으로 변함) 교체가 용이해집니다.

How to wire oAuth

이 게시물을 계기로 작성된 전체 구현은 Rubix Studios 블로그에 있으며, OAuth 흐름부터 컬렉션 설정, 커스텀 전략 자체까지 Payload v3 설정을 상세히 분해하고, CMS를 무상태(stateless)로 유지하면서도 원활한 관리 경험을 제공하는 방법을 다룹니다. 이미 Payload를 사용 중이거나 마이그레이션을 계획 중이며, 인위적인 코드 조각이 아닌 실제 코드베이스에서 어떻게 구현되는지 보고 싶다면, 다음 walkthrough를 참고하세요: PayloadCMS Custom Auth Strategy – Rubix Studios.

Back to Blog

관련 글

더 보기 »

실험적인 Hono auth npm 패키지

제가 만들고 있는 것은 개발자들이 일반적인 보일러플레이트인 login, register, JWT, email verification 등을 작성하지 않고도 앱에 바로 넣을 수 있는 auth 패키지입니다.