Ch 01. 로그인이 필요한 이유 — 인증의 개념
도서관에 들어가려면 회원증을 보여줘야 합니다. 직원실에는 직원만 들어갈 수 있습니다. 특별 열람실에는 교수나 연구원만 입장 가능합니다. 이 세 가지 상황은 모두 비슷해 보이지만, 사실 다른 개념입니다.
첫 번째는 "당신이 누구인지" 확인하는 것이고, 두 번째와 세 번째는 "당신이 무엇을 할 수 있는지" 결정하는 것입니다.
인증과 인가 — 비슷하지만 다른 두 개념
인증(Authentication)은 신원 확인입니다. "당신이 정말 누구인가?"를 묻습니다. 로그인 과정이 바로 인증입니다. 이메일과 비밀번호를 입력하면 시스템이 "맞습니다, 당신은 홍길동이군요"라고 확인해줍니다.
인가(Authorization)는 권한 확인입니다. "당신이 이것을 할 수 있는가?"를 묻습니다. 로그인은 했지만 모든 기능을 쓸 수 있는 건 아닙니다. 일반 사용자는 다른 사람의 글을 삭제할 수 없고, 관리자 페이지에 접근할 수 없습니다.
인증: "당신은 홍길동입니까?" → 예/아니오인가: "홍길동이 이 페이지를 볼 수 있습니까?" → 예/아니오
인증 없이 인가는 없습니다. 누구인지 모르면 무엇을 허용할지 결정할 수 없습니다.
쿠키 기반 세션 vs JWT 토큰
사용자가 로그인에 성공했다면, 그 사실을 어떻게 기억할까요? HTTP는 본래 상태 없는(stateless) 프로토콜입니다. 각 요청은 독립적이고, 이전 요청을 기억하지 않습니다. 그래서 로그인 상태를 유지하려면 별도의 장치가 필요합니다.
쿠키 기반 세션
전통적인 방식입니다. 서버가 로그인 성공 시 세션 ID를 생성하고 서버 메모리(또는 데이터베이스)에 저장합니다. 그 세션 ID를 쿠키에 담아 브라우저에 보냅니다. 이후 요청마다 브라우저는 쿠키를 함께 보내고, 서버는 그 세션 ID로 사용자를 식별합니다.
로그인 → 서버가 세션 저장 → 세션 ID를 쿠키로 전달요청 → 브라우저가 쿠키 첨부 → 서버가 세션 ID로 사용자 조회
장점은 서버가 세션을 완전히 통제한다는 것입니다. 로그아웃 시 서버에서 세션을 삭제하면 즉시 효력이 사라집니다. 단점은 서버가 세션을 저장해야 하므로 서버 확장(scale-out) 시 세션 동기화 문제가 생깁니다.
JWT 토큰
현대적인 방식입니다. 서버가 로그인 성공 시 JWT(JSON Web Token)를 생성해 클라이언트에 보냅니다. 서버는 아무것도 저장하지 않습니다. 이후 요청마다 클라이언트가 JWT를 함께 보내고, 서버는 토큰의 서명을 검증해 사용자를 식별합니다.
로그인 → 서버가 JWT 생성(서명) → 클라이언트가 저장요청 → 클라이언트가 JWT 첨부 → 서버가 서명 검증 → 사용자 식별
장점은 서버가 상태를 저장하지 않아 수평 확장이 쉽다는 것입니다. 단점은 로그아웃해도 토큰이 만료되기 전까지 유효하다는 것입니다. (블랙리스트로 해결 가능하지만 복잡해집니다.)
| 구분 | 세션 방식 | JWT 방식 |
|---|---|---|
| 저장 위치 | 서버 | 클라이언트 |
| 서버 부하 | 세션 조회 쿼리 발생 | 없음 |
| 즉시 무효화 | 가능 | 어려움 |
| 확장성 | 세션 동기화 필요 | 자유로움 |
Next.js에서 인증이 동작하는 위치
Next.js는 서버와 클라이언트가 혼재하는 환경입니다. 인증 역시 여러 곳에서 동작합니다.

미들웨어(middleware.ts): 가장 먼저 실행됩니다. 모든 요청이 페이지나 API에 도달하기 전에 통과하는 관문입니다. 여기서 미인증 사용자를 로그인 페이지로 리다이렉트하면, 서버 컴포넌트나 API가 실행되기 전에 차단할 수 있어 효율적입니다.
서버 컴포넌트: 페이지가 렌더링될 때 서버에서 세션을 확인합니다. 미들웨어를 통과했더라도 추가로 권한을 확인하거나, 사용자 정보를 가져와 렌더링에 활용합니다.
API 라우트 핸들러: 데이터를 변경하는 API는 반드시 서버에서 다시 인증을 확인해야 합니다. 클라이언트는 신뢰할 수 없습니다.
클라이언트 컴포넌트: 로그인 상태에 따라 UI를 다르게 보여줍니다. "로그인" 버튼 대신 "내 프로필"을 보여주거나, 작성자에게만 편집 버튼을 표시하는 것입니다.
미들웨어와 서버 컴포넌트에서 중복으로 확인하는 게 낭비처럼 보일 수 있습니다. 하지만 이는 의도적인 심층 방어(defense in depth)입니다. 미들웨어는 빠른 차단, 서버 컴포넌트는 세밀한 권한 확인을 담당합니다.
다음 챕터에서는 NextAuth.js를 사용해 실제 로그인 시스템을 구현합니다.