티스토리 뷰
📌 NestJS + Prisma + Next.js로 만드는 웹 애플리케이션 첫걸음 - 애자일 쇼핑몰 프로젝트 - 인증 및 보안
octo54 2025. 3. 13. 13:45📌 NestJS + Prisma + Next.js로 만드는 웹 애플리케이션 첫걸음 - 애자일 쇼핑몰 프로젝트 - 인증 및 보안
1. 웹 애플리케이션에서 인증과 보안이 중요한 이유
쇼핑몰 애플리케이션은 사용자 정보를 다루며 결제 시스템을 포함하기 때문에, 강력한 보안이 필수적입니다.
특히, **사용자 인증(Authentication) 및 권한 관리(Authorization)**를 제대로 구현해야 보안 취약점을 줄이고 데이터 보호가 가능합니다.
✅ 인증 및 보안의 주요 목표:
- 사용자 데이터 보호 (비밀번호 암호화 및 안전한 로그인)
- JWT 토큰 기반 인증 적용 (JSON Web Token)
- 관리자와 일반 사용자 구분 (RBAC, Role-Based Access Control)
- 보안 위협 차단 (SQL Injection, XSS, CSRF 방어)
2. JWT(JSON Web Token) 기반 인증 시스템
2.1. JWT란?
JWT(JSON Web Token)는 사용자 인증에 사용되는 토큰 방식의 인증 시스템입니다.
- 사용자가 로그인하면 JWT 토큰을 발급받아 이후 요청 시 인증 수단으로 사용
- 서버는 JWT를 검증하여 사용자의 신원을 확인
- 세션 기반 인증보다 확장성과 보안성이 높음
💡 JWT의 구조 (Header + Payload + Signature)
{
"alg": "HS256",
"typ": "JWT"
}
{
"id": 1,
"email": "user@example.com",
"role": "customer",
"exp": 1712345678
}
✅ JWT는 클라이언트가 보관하며, API 요청 시 Authorization: Bearer <TOKEN> 형태로 전달됩니다.
3. NestJS에서 JWT 기반 인증 구현
3.1. JWT 관련 패키지 설치
npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcryptjs
npm install --save-dev @types/bcryptjs
3.2. JWT 모듈 설정
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
@Module({
imports: [
JwtModule.register({
secret: process.env.JWT_SECRET, // .env 파일에서 가져오기
signOptions: { expiresIn: '1h' },
}),
],
controllers: [AuthController],
providers: [AuthService],
})
export class AuthModule {}
3.3. 사용자 로그인 및 JWT 발급
💡 로그인 시 비밀번호를 비교하고, JWT 토큰을 발급합니다.
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcryptjs';
@Injectable()
export class AuthService {
constructor(private jwtService: JwtService) {}
async validateUser(email: string, password: string) {
const user = await this.findUserByEmail(email);
if (user && bcrypt.compareSync(password, user.password)) {
return this.generateToken(user);
}
return null;
}
async generateToken(user: any) {
return this.jwtService.sign({
id: user.id,
email: user.email,
role: user.role,
});
}
}
✅ 로그인 성공 시 JWT를 발급하며, 이후 요청에서 사용됩니다.
4. RBAC(역할 기반 접근 제어) 적용
4.1. 사용자 역할(Role) 설정
쇼핑몰 애플리케이션에서는 사용자의 역할을 기반으로 권한을 제한해야 합니다.
💡 예제: User 모델에서 역할 추가 (schema.prisma)
model User {
id Int @id @default(autoincrement())
email String @unique
password String
role String @default("customer") // customer, admin
}
4.2. 관리자 전용 API 보호 (Guard 적용)
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
if (!requiredRoles) return true;
const request = context.switchToHttp().getRequest();
const user = request.user;
return requiredRoles.includes(user.role);
}
}
💡 이제 특정 API에 관리자만 접근하도록 설정할 수 있습니다.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RolesGuard } from './roles.guard';
@Controller('admin')
@UseGuards(RolesGuard)
export class AdminController {
@Get('dashboard')
getAdminDashboard() {
return { message: '관리자 대시보드' };
}
}
✅ 이제 GET /admin/dashboard API는 관리자만 접근 가능!
5. 보안 강화를 위한 추가 조치
5.1. 비밀번호 암호화 (Bcrypt 적용)
사용자 비밀번호를 암호화하여 저장해야 합니다.
💡 비밀번호 암호화 예제 (users.service.ts)
import * as bcrypt from 'bcryptjs';
async createUser(email: string, password: string) {
const hashedPassword = await bcrypt.hash(password, 10);
return this.prisma.user.create({
data: { email, password: hashedPassword },
});
}
✅ 이제 데이터베이스에 저장되는 비밀번호는 해싱되어 보호됩니다.
5.2. CORS 설정
CORS(Cross-Origin Resource Sharing)는 다른 도메인에서 API를 호출할 수 있도록 허용하는 설정입니다.
💡 NestJS의 main.ts에서 CORS 설정 추가
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: 'https://example.com', // 허용할 도메인 설정
credentials: true,
});
await app.listen(3000);
}
bootstrap();
✅ CORS를 설정하면 프론트엔드에서 API를 안전하게 호출할 수 있습니다.
6. 보안 위협 방지 (SQL Injection, XSS, CSRF 대응)
✅ SQL Injection 방어
- Prisma ORM을 사용하면 쿼리 빌더를 활용하여 SQL Injection을 방지할 수 있습니다.
- findMany(), create() 등의 메서드를 사용하면 직접 SQL 쿼리를 실행하는 것보다 안전합니다.
✅ XSS(Cross-Site Scripting) 방어
- 입력값을 검증하여 악성 스크립트 삽입을 방지 (class-validator 활용)
- escape-html 패키지를 사용하여 HTML 태그 제거
✅ CSRF(Cross-Site Request Forgery) 방어
- JWT를 사용하면 CSRF 공격 위험이 줄어듦
- API 요청 시 CSRF 토큰 검증을 추가할 수도 있음
🎯 마무리하며
이번 챕터에서는 NestJS + Prisma를 활용하여 JWT 기반 인증 및 보안을 적용하는 방법을 살펴보았습니다.
다음 단계에서는 3.5. API 문서화 및 테스트를 다루겠습니다. 🚀
'project > NestJS + Prisma로 만드는 웹 애플리케이션 첫걸음 - 쇼핑몰' 카테고리의 다른 글
- Total
- Today
- Yesterday
- AI챗봇
- nextJS
- rag
- Prisma
- NestJS
- Next.js
- SEO최적화
- REACT
- 개발블로그
- 딥러닝
- nodejs
- PostgreSQL
- Docker
- JAX
- 백엔드개발
- seo 최적화 10개
- Python
- flax
- gatsbyjs
- llm
- Ktor
- 웹개발
- 프론트엔드면접
- App Router
- 프론트엔드
- fastapi
- 파이썬알고리즘
- SEO 최적화
- kotlin
- CI/CD
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |