웹 애플리케이션의 보안은 현대 디지털 환경에서 매우 중요한 요소입니다. 특히, 인증(Authentication)과 인가(Authorization)는 사용자의 신원을 확인하고, 특정 자원에 대한 접근 권한을 부여하는 과정으로, 웹 애플리케이션의 안전성을 보장하는 데 필수적입니다. 이번 포스트에서는 Nest.js를 활용하여 인증 및 인가 전략을 구현하는 방법에 대해 자세히 알아보겠습니다.
인증(Authentication)
인증은 사용자가 자신이 주장하는 사람임을 증명하는 과정입니다. 일반적으로 사용자 이름과 비밀번호를 통해 이루어지며, 사용자가 성공적으로 인증을 받으면 서버는 해당 사용자에게 토큰을 발급합니다. 이 토큰은 이후의 요청에서 신원을 증명하는 데 사용됩니다.
JWT(JSON Web Token) 기반 인증
- 사용자가 로그인할 때, 서버는 입력된 자격 증명을 검증합니다. 이 과정은 사용자의 비밀번호가 데이터베이스에 저장된 해시와 일치하는지를 확인하는 방식으로 이루어집니다.
- 검증이 완료되면, 서버는 JWT를 생성하여 클라이언트에게 반환합니다. 이 토큰은 사용자의 신원을 확인하는 데 필요한 정보를 포함하고 있으며, 클라이언트는 이후 요청 시 이 토큰을 포함하여 서버에 요청함으로써 자신의 신원을 증명하게 됩니다.
// AuthService.ts
import { Injectable } from '@nestjs/common';
import * as jwt from 'jsonwebtoken';
@Injectable()
export class AuthService {
async login(user: any) {
const payload = { username: user.username, sub: user.userId };
return {
access_token: jwt.sign(payload, 'secretKey', { expiresIn: '60s' }),
};
}
}
인가(Authorization)
인가란 인증된 사용자가 특정 자원이나 기능에 접근할 수 있는지를 결정하는 과정입니다. 이는 보통 역할 기반 액세스 제어(RBAC)를 통해 이루어지며, 각 사용자에게 부여된 역할에 따라 접근 가능한 리소스를 제한합니다. 이러한 인가 과정은 웹 애플리케이션의 보안성을 더욱 강화하는 데 기여합니다.
역할 기반 인가
- 각 사용자에게 역할(Role)을 부여하고, 해당 역할에 따라 접근 가능한 리소스를 제한합니다. 예를 들어, 관리자는 모든 리소스에 접근할 수 있지만 일반 사용자는 일부 리소스만 접근할 수 있도록 설정할 수 있습니다. 이를 통해 시스템의 보안을 더욱 강화할 수 있습니다.
// roles.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return roles.includes(user.role);
}
}
인증 전략 구현
Nest.js에서는 Passport 모듈을 활용하여 다양한 인증 전략을 손쉽게 구현할 수 있습니다. JWT 외에도 OAuth2와 같은 다른 인증 방식을 사용할 수 있으며, 이를 통해 다양한 요구 사항에 맞는 인증 시스템을 구축할 수 있습니다.
단계별 설명
Passport 설치:
npm install @nestjs/passport passport passport-jwt
JWT 전략 설정:
// jwt.strategy.ts import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: 'secretKey', }); } async validate(payload: any) { return { userId: payload.sub, username: payload.username }; } }
모듈 내에서 적용:
// auth.module.ts import { Module } from '@nestjs/common'; import { JwtModule } from '@nestjs/jwt'; import { AuthService } from './auth.service'; import { JwtStrategy } from './jwt.strategy'; @Module({ imports:[ JwtModule.register({ secret:'secretKey', signOptions:{expiresIn:'60s'}, }), ], providers:[AuthService, JwtStrategy], }) export class AuthModule {}
컨트롤러에서 보호하기:
// app.controller.ts import { Controller, Get, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Controller('app') export class AppController { @UseGuards(AuthGuard('jwt')) @Get('protected') getProtectedResource() { return "This is a protected resource!"; } }
결론
인증 및 인가는 Nest.js 애플리케이션의 안전성을 높이는 데 필수적입니다. JWT와 같은 기술들을 활용하면 효율적이고 안전한 방식으로 사용자 관리를 할 수 있으며, 이를 통해 더 나은 사용자 경험과 시스템 안정성을 제공할 수 있습니다. Roles와 Guards를 적절히 조합해 필요한 부분만 보호하도록 설계하면 더욱 효과적인 보안을 구축할 수 있습니다. 이러한 접근 방식은 웹 애플리케이션의 전반적인 보안 수준을 향상시키고, 사용자 데이터의 안전성을 보장하는 데 기여합니다.
'프로그래밍 > Nest.js' 카테고리의 다른 글
데이터베이스 연결: Nest.js에서 TypeORM과 Mongoose 활용하기 (0) | 2025.03.22 |
---|---|
Nest.js에서 프로바이더의 중요성과 활용 (0) | 2025.03.22 |
모듈의 중요성과 활용: Nest.js에서의 코드 구조화 (0) | 2025.03.21 |
Nest.js에서의 미들웨어 활용: 글로벌 및 모듈별 적용 방법 (0) | 2025.03.21 |
커스텀 가드 구현으로 애플리케이션 보안 강화하기 (0) | 2025.03.21 |