배꼽파지 않도록 잘 개발해요

[NestJS] service 클래스 내에서의 함수 분리의 중요성 본문

BackEnd/Express / NestJS

[NestJS] service 클래스 내에서의 함수 분리의 중요성

꼽파 2024. 8. 26. 16:32

현재 진행하고 있는 프로젝트의 로그인 단계는 대략 7단계를 거친다.

코드 개발 중이라서 이보다 많아질 수 있다. 아직 부족하다.

 

auth.service.ts

 

클래스 안에 특정 함수를 정의하고, 이 함수를 다른 함수가 재사용하는 형태가 되었다. 쉽게 말해 클래스 안에서 한 함수를 다른 함수가 끌어다 쓰고 있는 상황이다.

지금 로그인 로직만해도 7단계를 거치고 있는데, 이러다보면 AuthService에는 메서드들이 넘쳐나서 개발할 때 필요한 메서드를 쉽게 찾을 수 없다.

 

클라이언트에서 리퀘스트가 온다고 하면

AuthController의 로그인 API
→ AuthService의 로그인 메서드


이런식으로 깔끔하게 거쳐가게 하도록 하고 싶다.

로그인 메서드에 필요한 나머지 메서드들은 AuthService에서 재사용하는 것이 아니라,
각각 분리된 서비스 클래스를 만들고, 그곳에서 재사용하는게 낫겠다 싶었다.

AuthController의 로그인 API 
→  AuthService의 로그인 메서드
→  AuthSignInService, AuthSessionService, AuthPasswordService, AuthUserService의 중 연결된 메서드

 

그래서 코드를 각각 분리해줬다.

 

주의) 로그인 코드는 아직 개발 중이라 엉성할 수 있습니다.

import { ConflictException, Inject, Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UsersEntity } from 'src/users/entities/users.entity';
import { Repository } from 'typeorm';
import { CreateUserDto, SignInUserDto } from './dto';
import Redis from 'ioredis';
import { LoginsEntity } from './entities/logins.entity';
import { AuthPasswordService, AuthSessionService, AuthSignInService, AuthUserService } from './services';
import { Request, Response } from 'express';

@Injectable()
export class AuthService {
    constructor(
        @Inject('REDIS_CLIENT')
        private readonly redisClient: Redis,

        private readonly authUserService: AuthUserService,
        private readonly authPasswordService: AuthPasswordService,
        private readonly authSessionService: AuthSessionService,
        private readonly authSignInService: AuthSignInService
    ){}

    // 회원가입
    async signUp(createUserDto: CreateUserDto) {
        await this.authUserService.createUser(createUserDto);
    }

    // 회원탈퇴
    async withDraw(sessionId: string) {
        await this.authUserService.deleteUser(sessionId);
    }

    // 로그인
    async signIn(signInUserDto: SignInUserDto, req: Request, res: Response) {
        const { email, password } = signInUserDto;

        // 1. 이메일로 회원 찾기
        const user = await this.authUserService.findUserByEmail(email);

        if (!user) throw new UnauthorizedException('User not exist');

        // 2. 비밀번호 검증
        const isPasswordMatch = await this.authPasswordService.matchPassword(password, user.password);

        어쩌구 저쩌구~~~~~~~~~~~~~~

        // 6. 쿠키 발급
        await this.authSessionService.sendCookie(res, sessionId);

        // 7. 로그인 성공 메시지 리턴
        return { message : "로그인에 성공하였습니다." }
    }
}

 

이런식으로 database를 거쳐 authService 전까지 각 기능이 세분화된 메서드들을 별도의 클래스에 분리한다.

authService의 특정 메서드는 authController의 특정 API에 1:1 대응되도록 하였다.

각 서비스가 단일 책임 원칙을 따르게 하였고, 코드의 가독성유지보수성이 높아진다.

저번 프로젝트에는 정신이 없어서 이런 것도 신경을 못 썼는데, 이렇게 메서드를 분리하는 것도 많이 연습을 해야될 것 같다.


bcrypt 타입 인식 못하는 오류 해결

 

다음 명령어를 터미널에 입력한다.

npm install --save-dev @types/bcrypt

 

컴파일 오류가 나지 않는다.

728x90