git remote update
로 업데이트
3. Jira에서 커밋 메세지 받아와서 커밋하기
4. 연동됬는지 확인
로그인 회원가입 백엔드 구현, jwt인증 구현, 리프래시 토큰 구현, 마이페이지 기능, 마이페이지 수정 구현
제일 먼저 email 모듈과 auth 모듈, user 모듈을 만들어 주었다.
기존에는 database.provider.ts를 사용해서 db를 사용하였다.
하지만 typeORM의 표준 방식인 database.module.ts로 DB정보를 가져오는것으로 바꾸었는데 그 이유는 다음과 같다.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from 'src/user/user.entity';
import { EmailVerificationToken } from 'src/email/email.entity';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: '<>',
port: <>,
username: '<>',
password: '<>',
database: '<>',
entities: [__dirname + '/../**/*.entity.{js,ts}'],
synchronize: true,
}),
],
})
export class DatabaseModule {}
연결 풀링이나, 재연결 등의 로직을 자동으로 처리해준다. 또한
간편하게 Repository를 주입할 수 있다. 기존에는
// 기존 방식 (복잡)
@Inject('USER_REPOSITORY')
private userRepository: Repository<User>
위와 같이 @Inject로 의존성 주입을 해야했는데
이제는
// 표준 방식 (간단)
@InjectRepository(User)
private userRepository: Repository<User>
위와 같이 @InjectRepository로 주입하려는 요소를 명확하게 하고 이름도 간단히 적을 수 있다.
또한 기존에는 모듈에 Repository를 포함할 때도
// 복잡한 설정
@Module({
imports: [DatabaseModule],
providers: [...userProviders, UserService],
})
export class UserModule {}
위와 같이 프로바이더와 데이터베이스 모듈을 넣어줘야했는데 이제는
// 간단한 설정
@Module({
imports: [TypeOrmModule.forFeature([User])],
providers: [UserService],
})
export class UserModule {}
위와 같이 TypeOrmModule.forFeature([User])를 쓰는것으로 간단하게 User 엔티티와 연동할 수 있다.
Post로 무언가를 넘길 때는 웬만해서 DTO를 사용해서 넘기는 것이 좋다.
로그인 단위에서 JWT 인증을 위해서는 JWT Guard를 생성해서 이를 각 마이페이지에 적용하는것이 좋다.
import {
Injectable,
CanActivate,
ExecutionContext,
UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Request } from 'express';
// JWT 인증 가드
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractTokenFromHeader(request);
console.log('token', token);
if (!token) {
throw new UnauthorizedException('JWT 토큰이 필요합니다.');
}
// JWT 토큰 검증
try {
// JWT 토큰 검증 및 추출 정보 얻어오기기
const payload = await this.jwtService.verifyAsync(token);
console.log('JWT Payload:', payload); // 디버깅용 로그
// 요청 객체에 사용자 정보를 추가
request['user'] = payload;
return true;
} catch {
throw new UnauthorizedException('유효하지 않은 JWT 토큰입니다.');
}
}
// JWT 토큰 추출
private extractTokenFromHeader(request: Request): string | undefined {
const [type, token] = request.headers.authorization?.split(' ') ?? [];
return token;
}
}
JwtService의 CanActivate 클래스를 상속시켜
request에서 token을 가져와서 토큰을 검증하고 유효한 토큰인지 확인한다.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
// 현재 사용자 정보 추출 데코레이터
export const CurrentUser = createParamDecorator(
// 현재 사용자 정보 추출
(data: unknown, ctx: ExecutionContext) => {
// 요청 객체에서 사용자 정보 추출
const request = ctx.switchToHttp().getRequest();
// 사용자 정보 반환
return request.user;
},
);
현재 사용자의 정보를 추출해서 jwt와 비교하기위해 데코레이터를 만든다.
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
import { CurrentUser } from 'src/auth/user.decorator';
위를 삽입하고
@Get('/mypage')
@UseGuards(JwtAuthGuard)
async myPage(@CurrentUser() user: any)
request에서 user를 받을때 위와 같이 받고 Guards를 설정해놓으면 된다.
동적 모듈을 구성하고, 그 모듈을 여러 군데에서 사용할 수 있도록 사용한다.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from 'src/user/user.entity';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'codeplanner',
password: 'codeplanner1234',
database: 'codeplanner',
entities: [__dirname + '/../**/*.entity.{js,ts}'],
synchronize: true,
}),
],
})
export class DatabaseModule {}