user.entity.ts
@Entity({ name: 'users' })
export class UserEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
email: string;
@Column()
username: string;
@Column({ default: '' })
bio: string;
@Column({ default: '' })
image: string;
@Column({ select: false })
password: string;
...
{select :false}
를 설정하면, 해당 컬럼이 기본적으로 반한 결과에 포함되지 않도록 지정하는 역할을 한다.
비밀번호 필드에 select false를 설정하는 이유는 보안과 불필요한 데이터 노출을 방지하기 위해서이다.
비밀번호는 민감한 정보로, 보통은 클라이언트에게 반환되면 안 되는 데이터이다. 따라서, select false 옵션을 설정함으로써 기본적으로 비밀번호를 선택하지 않는다고 한다.
여태껏 비밀번호도 그냥 전부 다 return 했었는데.. 이를 알고나니까 또 새롭다.
이렇게 설정하면 기본적으로 데이터베이스 쿼리에서는 비밀번호 필드가 제외되어 반환되지 않는다. 그러나 로그인과 같이 비밀번호 필드값이 필요할 경우, 명시적으로 해당 필드를 선택해주어야 하는데,
user.service.ts
async login(loginUserDto: LoginUserDto): Promise<UserEntity> {
const user = await this.userRepository.findOne({
where: {
email: loginUserDto.email,
},
//필드 선택 - 비밀번호
select: ['id', 'username', 'email', 'bio', 'image', 'password'],
});
if (!user) {
throw new HttpException(
'Credentials are not valid',
HttpStatus.UNPROCESSABLE_ENTITY,
);
}
//bcrypt로 비밀번호 compare
const isPasswordCorrect = await compare(
loginUserDto.password,
user.password,
);
if (!isPasswordCorrect) {
throw new HttpException(
'Credentials are not valid',
HttpStatus.UNPROCESSABLE_ENTITY,
);
}
delete user.password; //password를 return 값에서 지움
return user;
}
select: ['id', 'username', 'email', 'bio', 'image', 'password']
는 findOne 메서드에서 선택할 필드를 명시적으로 지정하면 된다.
여기서 password를 입력해주면 사용자가 입력한 비밀번호와 저장된 비밀번호를 비교할 수 있게 된다.
login 메서드에서는 로그인을 처리하고 유효성을 검사한 후, return 전에 delete user.password
를 사용하여 비밀번호 필드를 삭제한 사용자 객체를 반환한다. 이를 통해 보안과 불필요한 데이터 노출을 방지할 수 있다!