웹 개발
배포 후 관리자만 401을 받았던 쿠키 속성 점검 체크리스트
로컬에서는 로그인되는데 HTTPS 운영 환경에서 관리자 요청만 401이 된 원인을 쿠키 속성별로 확인한 체크리스트입니다.
로그인 성공과 인증 유지 성공은 달랐다
로그인 API의 응답은 200이었고 브라우저에도 성공 알림이 떴다. 그런데 관리자 페이지에서 글 목록을 요청하면 401이 반복됐다. 로컬 HTTP 환경에서는 같은 코드가 동작해서 서버 비밀번호나 세션 저장 로직부터 의심했지만, 실제 문제는 브라우저가 세션 쿠키를 다음 요청에 보내지 않는 것이었다.
운영 도메인이 바뀐 날 쿠키 설정을 직접 확인하지 않은 것이 시작이었다. 개발자 도구 Network 탭에서 로그인 응답의 Set-Cookie와 다음 API 요청의 Cookie 헤더를 나란히 보는 방식으로 범위를 좁혔다.
속성을 한 번에 하나씩 확인했다
내가 확인한 순서는 다음과 같다.
Domain과Path가 관리자 요청 경로와 맞는가- 운영이 HTTPS인데
Secure가 빠지거나, 반대로 개발 HTTP에서 무조건 켜져 있지 않은가 - 프론트와 API의 사이트 관계에 맞는
SameSite값인가 - 쿠키의 만료 시간이 서버 시간과 엇갈리지 않는가
- 응답을 받는 fetch에 필요한 credentials 설정이 있는가
동일 사이트의 브라우저 요청에서는 우선 명시적으로 기본값을 고정했다.
response.cookies.set('session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 60 * 60 * 24 * 7,
})
다른 origin에서 호출하는 구조라면 SameSite만 바꾸는 것으로 끝나지 않는다. 서버의 CORS 허용 origin과 Access-Control-Allow-Credentials: true, 클라이언트의 credentials: 'include'가 함께 맞아야 한다. Access-Control-Allow-Origin: *와 credentials를 동시에 쓸 수 없다는 것도 테스트에서 다시 확인했다.
fetch('/api/admin/posts', {
method: 'GET',
credentials: 'include',
})
운영 전 체크박스
- 로그인 응답에 세션 쿠키가 실제로 존재한다
- 쿠키가
HttpOnly라서 페이지 JavaScript가 토큰을 읽지 못한다 - HTTPS 환경에서
Secure가 적용된다 Path=/로 관리자 API에도 전송된다- 프록시가
Set-Cookie의 속성을 지우지 않는다 - 만료된 쿠키와 오래된 도메인 쿠키를 브라우저에서 제거했다
- 로그아웃 응답의 삭제 쿠키가 생성 쿠키와 같은 path/domain을 사용한다
마지막으로 남긴 규칙
401을 보면 곧바로 세션 생성 코드를 고치지 않고, 먼저 “쿠키가 저장됐는가 → 해당 요청에 전송됐는가 → 서버가 읽었는가”를 세 단계로 나눈다. 이 순서를 지키면 로컬과 운영의 차이를 훨씬 빨리 찾을 수 있고, 인증 토큰을 로그에 출력하는 위험한 디버깅도 피할 수 있다.