[Node.js – 기초 강좌] 7-1. 사용자 인증하기(Authentication) – (Session & Cookie 사용)

사용자 인증은 시스템에 접근하는 사용자의 신원을 확인하는 과정입니다.

보안의 중요한 요소로, 다양한 방식으로 구현될 수 있습니다.

여기서는 세션과 쿠키를 이용한 인증, 그리고 JSON Web Token (JWT)을 이용한 토큰 기반 인증에 대해 알아보겠습니다.

세션(Session)을 과 쿠키(Cookie)를 이용한 인증

개요

세션(Session)쿠키(Cookie)는 웹 애플리케이션에서 상태 정보를 저장하고 관리하는 중요한 메커니즘입니다.

이 둘은 서로 밀접하게 연관되어 있으며, 주로 사용자의 인증 및 데이터 유지에 사용됩니다.

아래에서 각각의 개념과 작동 방식을 자세히 설명하겠습니다.

인증-쿠키-session-cookie

세션(Session) 이란?

서버 측에서 사용자의 상태를 저장합니다.

사용자가 로그인하면 서버는 세션을 생성하고, 세션 ID를 생성하여 이를 클라이언트에게 전달합니다.

클라이언트는 이 세션 ID를 쿠키에 저장하고, 이후 요청(Request) 시마다 이를 서버에 전송하여 인증을 유지합니다.

다음과 같은 특징을 갖습니다.

  • 상태 유지: 사용자가 로그인하면, 서버는 세션을 생성하고 해당 사용자의 정보를 세션에 저장합니다. 이후 사용자가 애플리케이션의 다른 페이지로 이동해도 세션을 통해 사용자의 상태를 유지할 수 있습니다.
  • 서버 측 저장: 세션 데이터는 서버에 저장되며, 클라이언트는 세션 ID만을 보유합니다. 이로 인해 데이터 유출 위험이 줄어듭니다.
  • 단기 저장: 세션은 보통 사용자가 웹 브라우저를 닫거나 로그아웃할 때 만료됩니다. 세션의 수명은 서버 설정에 따라 조정할 수 있습니다.

세션의 동작 방식

세션은 일반적으로 다음과 같은 방식으로 동작합니다:

  1. 클라이언트 요청: 클라이언트(사용자)가 서버에 요청을 보냅니다.
  2. 세션 생성: 서버는 요청을 처리하고 새로운 세션을 생성합니다. 이 세션은 고유한 세션 ID를 가지며, 서버의 메모리나 데이터베이스 등에 저장됩니다.
  3. 세션 ID 전달: 서버는 세션 ID를 클라이언트에 쿠키로 전달합니다.
  4. 클라이언트 재요청: 클라이언트가 서버에 다시 요청을 보낼 때, 이전에 받은 세션 ID를 쿠키에 포함시켜 보냅니다.
  5. 세션 참조: 서버는 세션 ID를 참조하여 해당 사용자의 세션 정보를 조회하고, 상태를 유지합니다.

세션 유지 기간

세션의 유지 기간(Session Lifetime)은 세션이 유효한 시간 범위를 말합니다. 이 기간이 지나면 세션은 만료되어 더 이상 유효하지 않게 됩니다. 세션 유지 기간은 서버 측에서 설정할 수 있으며, 보통 다음과 같이 설정됩니다:

  • 기본 설정: 세션 라이브러리나 프레임워크에서 기본적으로 설정된 시간.
  • 사용자 지정: 개발자가 직접 설정한 시간. 예를 들어, 1시간, 24시간 등으로 설정할 수 있습니다.
  • 무작위 종료: 브라우저가 닫힐 때 세션이 종료되는 방식. 이 경우 쿠키가 ‘세션 쿠키’로 설정됩니다.

쿠키(Cookie) 란?

클라이언트 측에 데이터를 저장하는 작은 파일입니다.

쿠키에는 세션 ID나 사용자 정보 등이 포함될 수 있습니다.

쿠키는 클라이언트가 서버에 요청을 보낼 때마다 함께 전송되어 사용자를 식별하는 데 사용됩니다.

다음과 같은 특징을 갖습니다.

  • 클라이언트 측 저장: 쿠키는 사용자의 웹 브라우저에 저장되며, 서버가 아닌 클라이언트 측에서 관리됩니다.
  • 키-값 쌍: 쿠키는 키-값 쌍으로 데이터를 저장합니다.만료 시간: 쿠키는 유효 기간을 가질 수 있으며, 만료되면 자동으로 삭제됩니다. 만료 시간이 설정되지 않은 쿠키는 세션 쿠키가 되며, 브라우저가 닫힐 때 삭제됩니다.
  • 도메인 및 경로 제한: 쿠키는 특정 도메인 및 경로에서만 접근할 수 있도록 제한할 수 있습니다.

예제

먼저 다음 cmd를 통해 project를 생성 및 초기화 합니다.

$ mkdir 07_auth_session_cookie
$ cd 07_auth_session_cookie

$ npm init -y
$ npm install express express-session cookie-parser body-parser
$ npm install @types/express @types/express-session @types/cookie-parser @types/body-parser typescript ts-node-dev --save-dev
$ tsc --init

예제코드

다음과 같이 express-session type을 확장합니다.

/src/types/express-ssession/index.d.ts

import "express-session";

declare module "express-session" {
  interface SessionData {
    user: { [key: string]: any };
  }
}

/src/app.ts

/login을 통해 로그인 시, session을 정보를 저장합니다.

/profile request를 수신했을 때 session 정보를 확인하여 리턴합니다.

/logout을 통해 session을 종료 합니다.

import bodyParser from "body-parser";
import cookieParser from "cookie-parser";
import express, { Request, Response } from "express";
import session from "express-session";

const app = express();
const PORT = 50001;

// 미들웨어 설정
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(
  session({
    secret: "your_secret_key",
    resave: false,
    saveUninitialized: true,
    cookie: { secure: false }, // HTTPS를 사용하는 경우 true로 설정
  })
);

interface User {
  id: number;
  name: string;
}

const fakeUser: User = { id: 1, name: "John Doe" };

// 로그인 엔드포인트
app.post("/login", (req: Request, res: Response) => {
  const { username, password } = req.body;

  // 실제로는 데이터베이스에서 사용자 인증을 수행해야 합니다.
  if (username === "admin" && password === "password") {
    req.session.user = fakeUser;
    res.send("Login Success");
  } else {
    res.status(401).send("로그인 실패");
  }
});

// 프로필 엔드포인트
app.get("/profile", (req: Request, res: Response) => {
  if (req.session.user) {
    res.send(`Hi, ${req.session.user.name}`);
  } else {
    res.status(401).send("Need to login");
  }
});

// 로그아웃 엔드포인트
app.post("/logout", (req: Request, res: Response) => {
  req.session.destroy((err) => {
    if (err) {
      return res.status(500).send("Failed to logout");
    }
    res.send("Successfully logged out");
  });
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

테스트

Postman을 통해 테스트를 진행해 봅니다.

Login 실시

usernamepassword 에 인증정보 (admin / password)를 body에 넣어 post 합니다. -> 로그인 성공

success-login-test

정보 획득

/profile을 통해 정보를 요청합니다.

세션을 확인하여 정상적으로 정보가 response 됩니다.

success-profile-test

Logout

/logout 을 통해 세션을 종료합니다.

Logout-test

정보 획득 실패

세션이 종료 되어 정보가 response 되지 않습니다.

Failed to profile

참고 링크

Leave a Comment