로그인 유지 문제를 찾으려면 “쿠키냐 세션이냐”를 고르기보다 브라우저가 어떤 값을 보내고 서버가 어디서 상태를 찾는지 구분해야 합니다. win-j 관리자는 Django 세션 인증을 사용하므로, 브라우저의 세션 쿠키와 서버의 세션 저장소를 함께 확인하는 것이 출발점입니다.

현재 프로젝트의 로그인 흐름

현재 설정에는 Django SessionMiddleware와 AuthenticationMiddleware가 있으며 세션 엔진을 별도로 바꾸지 않습니다. Django 기본 DB 세션 백엔드를 사용하므로 브라우저에는 세션 키가, 서버 DB에는 그 키에 대응하는 세션 데이터가 저장되는 구조입니다. 운영 환경의 실제 쿠키 값이나 로그인 기록을 수집해 설명하는 것은 아닙니다. Django 세션 백엔드

  1. 서버가 로그인 자격을 확인합니다.
  2. Django 로그인 처리가 인증 정보를 세션에 기록합니다.
  3. 응답을 받은 브라우저가 세션 쿠키를 저장합니다.
  4. 이후 조건에 맞는 요청에 Cookie 헤더가 붙습니다.
  5. 서버가 세션을 조회해 사용자를 복원하고, 관리자 경로에서 staff 여부를 추가 검사합니다.

로그인 성공과 관리자 권한은 다른 조건입니다. 이 사이트의 staff 보호 경로는 비로그인 사용자뿐 아니라 staff가 아닌 사용자도 로그인 경로로 돌려보낼 수 있습니다. 로그인 화면으로 이동한다고 모두 쿠키 장애는 아닙니다.

쿠키는 전달 수단, 세션은 상태 관리

확인 대상 이 프로젝트의 기본 구성 문제를 찾을 위치
세션 식별자 브라우저의 sessionid 쿠키 개발자 도구의 Cookies
인증 관련 세션 데이터 서버의 Django 세션 DB 서버 세션 설정·DB 상태
관리자 접근 권한 사용자 모델의 active·staff 조건 계정과 경로의 권한 검사
CSRF 보호 CSRF 쿠키·토큰과 요청 검사 실패한 POST와 Origin·토큰

DB에 저장하는 세션은 웹 프로세스만 재시작했다고 반드시 사라지지 않습니다. DB 삭제, 세션 만료, 키 변경, 브라우저 쿠키 누락처럼 다른 원인을 확인해야 합니다. 캐시·메모리 백엔드를 사용하는 다른 서비스는 재시작의 영향이 다를 수 있습니다.

Set-Cookie와 Cookie에서 볼 차이

아래는 구조 설명용이며 실제 인증에 사용할 수 없는 값입니다.

Set-Cookie: sessionid=EXAMPLE_ONLY; Path=/; Secure; HttpOnly; SameSite=Lax

서버는 응답의 Set-Cookie로 속성까지 지정합니다. 다음 요청의 Cookie에는 보통 sessionid=EXAMPLE_ONLY처럼 이름과 값이 실리며 HttpOnly나 SameSite 속성을 그대로 보내는 것은 아닙니다.

HttpOnly는 JavaScript가 쿠키 값을 읽지 못하게 하지만 해당 쿠키가 붙은 요청 자체를 모두 막지는 않습니다. Secure는 보안 연결에서의 전송을 제한하며, SameSite는 사이트 간 요청에 쿠키를 포함하는 조건에 영향을 줍니다. Path·Domain·만료 시각도 쿠키 전송 범위에 관여합니다. HTTP 쿠키 속성

이 프로젝트는 세션 쿠키와 CSRF 쿠키의 Secure 설정을 환경변수로 읽습니다. 따라서 로컬 HTTP와 운영 HTTPS의 차이를 비교할 때 소스 기본값만 보고 현재 실행 값을 단정하지 않습니다. 브라우저의 쿠키 차단 사유와 실행 환경 설정을 함께 봅니다.

로그인 유지가 안 될 때 확인할 순서

  1. 로그인 응답에 Set-Cookie가 있었는지 확인합니다. 브라우저가 저장하지 않았다면 차단 사유를 봅니다.
  2. 다음 관리자 요청에 세션 쿠키가 실제로 붙었는지 확인합니다. 호스트 변경·경로·HTTPS 조건을 비교합니다.
  3. 쿠키가 전달됐다면 서버에서 만료되거나 유효하지 않은 세션인지 확인합니다.
  4. 세션이 유효하면 계정의 staff 권한을 확인합니다.
  5. 조회는 되는데 저장만 403이면 CSRF 토큰·Origin 등 POST 보호 조건을 따로 확인합니다.

개발자 도구로 Cookie 헤더를 복사해 공개 문의에 붙이지 않습니다. 재현 기록에는 쿠키의 존재 여부·속성·응답 상태만 남겨도 위 단계를 좁힐 수 있습니다.

세션 데이터가 항상 서버에만 있는 것은 아니다

프레임워크와 백엔드 선택에 따라 구조가 달라집니다. 예를 들어 Flask 기본 세션은 서명된 쿠키에 데이터를 저장합니다. 서명은 변조 확인을 위한 것이며 사용자가 내용을 읽지 못하게 암호화하는 기능은 아닙니다. 따라서 Flask의 session["user"] 예제를 보여주면서 반드시 서버 DB에 저장한다고 설명하면 부정확합니다. Flask 기본 세션 설명

JWT도 쿠키로 전달할 수 있고, 서버 세션도 HTTP API에 사용할 수 있습니다. “쿠키는 낮은 보안, 세션은 높은 보안”처럼 등급을 매기기보다 저장 위치·탈취 대응·만료·폐기·요청 보호를 구체적으로 설계해야 합니다. JWT 해독과 검증 구분과 함께 보면 형식과 전달 수단을 분리하기 쉽습니다.