[nestJS] 인증

리버 river·2025년 2월 2일
0

안녕하세요. NestJS에서 인증을 구현하는 방법에 대해 알아보려고 합니다.

인증과 인가, 헷갈리시죠?

개발을 하다 보면 '인증'과 '인가'라는 용어를 자주 마주치게 되는데요, 이 둘은 비슷하면서도 명확히 다른 개념입니다.

인증(Authentication)은 쉽게 말해 "너 누구야?"라고 물어보는 거예요. 우리가 서비스에 로그인할 때처럼, 사용자가 자신이 주장하는 사람이 맞는지 확인하는 과정입니다.

인가(Authorization)는 "너 이거 할 수 있어?"라고 물어보는 거예요. 예를 들어, 관리자만 접근할 수 있는 페이지에 일반 사용자가 들어가려고 할 때 체크하는 것처럼요.

다양한 인증 방식 살펴보기

NestJS에서는 여러 가지 인증 방식을 사용할 수 있는데요, 각각의 특징을 살펴보면서 어떤 상황에서 어떤 방식을 선택하면 좋을지 이야기해보려고 합니다.

JWT (JSON Web Token) - 요즘 가장 핫한 인증 방식

JWT는 요즘 가장 많이 사용되는 인증 방식인데요, 토큰 기반으로 동작합니다.

JWT는 마치 신분증같은 거예요. Header(신분증 형식), Payload(실제 정보), Signature(위조 방지 장치)로 구성되어 있죠. Base64로 인코딩되어 점(.)으로 구분된 문자열 형태로 만들어집니다.

이렇게 동작해요

  1. 사용자가 로그인에 성공하면 서버가 JWT를 발급해줘요
  2. 이후부터는 사용자가 요청할 때마다 이 JWT를 들고 와요
  3. 서버는 JWT를 확인하고 유효하면 요청을 처리해줍니다

좋은 점

  • 서버가 사용자 정보를 따로 저장할 필요가 없어요
  • 모바일이든 웹이든 어디서나 똑같이 쓸 수 있어요
  • 마이크로서비스 환경에서도 잘 동작해요

아쉬운 점

  • 토큰에 정보가 많으면 요청할 때마다 데이터가 커져요
  • 토큰을 탈취당하면 만료되기 전까지는 대응하기 어려워요

세션 기반 인증 - 전통적이지만 여전히 강력해요

세션은 전통적인 방식이지만, 여전히 많이 사용되고 있어요. 특히 서버에서 렌더링하는 웹사이트에서는 아직도 강력한 선택지죠.

이렇게 동작해요

  1. 로그인하면 서버에 세션을 만들고 세션ID를 줘요
  2. 사용자는 쿠키에 이 세션ID를 저장해두고 요청할 때마다 보내요
  3. 서버는 세션ID로 사용자를 확인하고 요청을 처리해요

좋은 점

  • 서버에서 완벽하게 제어할 수 있어요
  • 문제가 생기면 바로 세션을 없앨 수 있어요
  • 검증된 방식이라 안정적이에요

아쉬운 점

  • 서버가 여러 대면 세션 동기화가 필요해요
  • 사용자가 많아지면 서버 메모리를 많이 차지해요
  • 다른 도메인과의 통신이 까다로워요

OAuth 2.0 - 소셜 로그인의 표준

OAuth 2.0은 요즘 많이 보시는 '구글로 로그인하기', '카카오로 로그인하기' 같은 기능을 구현할 때 사용하는 표준 프로토콜이에요.

이렇게 동작해요

  1. 사용자가 '구글로 로그인' 같은 버튼을 클릭해요
  2. 구글 로그인 페이지로 이동해서 로그인하죠
  3. 우리 서비스가 사용자 정보를 받아올 수 있게 허용해주면
  4. 다시 우리 서비스로 돌아와서 자동으로 로그인이 완료돼요

좋은 점

  • 사용자가 비밀번호를 따로 기억할 필요가 없어요
  • 구글, 페이스북 같은 큰 기업의 보안을 믿을 수 있어요
  • 이메일, 프로필 사진 같은 정보를 쉽게 가져올 수 있어요

아쉬운 점

  • 외부 서비스에 의존하게 되요
  • 구현이 좀 복잡한 편이에요
  • 외부 서비스 연동이라 속도가 좀 느릴 수 있어요

API 키 인증 - 간단하지만 강력해요

API 키는 주로 서버와 서버 사이, 또는 개발자용 API를 제공할 때 많이 사용하는 방식이에요.

이렇게 동작해요

  1. 서비스에서 고유한 API 키를 발급받아요
  2. API 요청할 때마다 이 키를 함께 보내요
  3. 서버는 키가 유효한지 확인하고 요청을 처리해요

좋은 점

  • 구현이 정말 간단해요
  • 키만 확인하면 돼서 처리가 빨라요
  • API 사용량을 제한하거나 모니터링하기 쉬워요

아쉬운 점

  • 키가 유출되면 큰일 나요
  • 키를 관리하는 게 생각보다 귀찮아요
  • 세세한 권한 제어가 어려워요

실제로 한번 구현해볼까요?

자, 이제 NestJS에서 실제로 JWT 인증을 구현하는 방법을 알아볼게요. JWT를 선택한 이유는 현재 가장 많이 사용되는 방식이기도 하고, NestJS 공식 문서에서도 가장 자세히 다루고 있기 때문입니다.

1. 패키지부터 설치하기

npm install @nestjs/jwt @nestjs/passport passport passport-jwt

2. 인증 서비스 만들기

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(private readonly jwtService: JwtService) {}

  async login(user: any) {
    const payload = { sub: user.id, username: user.username };

    // 실제 서비스에서는 이렇게 토큰 두 개를 발급해요
    return {
      accessToken: this.jwtService.sign(payload, { expiresIn: '15m' }),
      refreshToken: this.jwtService.sign(payload, { expiresIn: '7d' }),
    };
  }

  async validateUser(username: string, password: string) {
    // 실제로는 DB에서 사용자를 찾아야 해요
    if (username === 'test' && password === 'password') {
      return { id: 1, username };
    }
    return null;
  }
}

3. JWT 전략도 필요

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET,
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}

4. 인증이 필요한 API 만들기

import { Controller, Get, UseGuards, Request } from '@nestjs/common';
import { JwtAuthGuard } from './jwt-auth.guard';

@Controller('profile')
export class ProfileController {
  @UseGuards(JwtAuthGuard)
  @Get()
  getProfile(@Request() req) {
    return req.user;
  }
}

더 안전하게 만들기

실제 서비스에서는 보안을 더 강화할 필요가 있습니다. 간단히 아래와 같은 방법들이 있어요.

  1. 토큰 만료 시간을 짧게: 액세스 토큰은 15분, 리프레시 토큰은 7일 정도로 설정해요
  2. 리프레시 토큰은 안전하게: Redis같은 곳에 저장해두고 관리하면 좋아요
  3. 토큰 검증은 꼼꼼하게: 서명도 확인하고, 만료 시간도 확인하고!
  4. 에러 처리도 중요해요: 인증 실패했을 때 친절한 메시지를 보여주세요
  5. HTTPS는 필수: 프로덕션 환경에서는 반드시 HTTPS를 사용해야 해요

마무리하며

지금까지 NestJS에서 인증을 구현하는 여러 가지 방법을 알아봤는데요, 마무리로 인증 방식 선택 가이드를 가볍게 정리해보록 하겠습니다.

  • REST API를 만든다면 JWT
  • 전통적인 웹사이트라면 세션
  • 소셜 로그인이 필요하다면 OAuth 2.0
  • 마이크로서비스를 구축한다면 JWT + Redis

실제로 구현하실 때는 프로젝트의 특성을 잘 고려해서 선택해야겠다는 생각이 듭니다~!

profile
프론트엔드 개발자

0개의 댓글

관련 채용 정보