Team_Mate/Backend

Service에서의 에러 핸들링 방법

_HelloWorld_ 2024. 12. 22. 13:05

 

// 사용자가 입력한 회원가입 정보가 유효한지 확인하는 함수
interface ValidSignUpInput {
  username: string;
  email: string;
  password: string;
}
export const validSignUpInput = (validProps: ValidSignUpInput) => {
  if (!validProps.username || !validProps.email || !validProps.password) {
    throw new Error('Username and email are required');
  }
  return;
}

// 사용자 회원가입 함수
interface SignUpProps {
  username: string;
  email: string;
  password: string;
  profile?: string;
}
export const signUp = async (signUpProps : SignUpProps): Promise<UserEntity> => {
  try {
    const existingUser = await userRepository.findOne({
      where: [
        { username: signUpProps.username },
        { email: signUpProps.email }
      ]
    });
    if (existingUser) {
      throw new Error('User already exists');
    }

    // Hash password
    const hashedPassword = hashPassword({password: signUpProps.password});

    // Create new user
    const newUser = userRepository.create({
      ...signUpProps,
      password: hashedPassword
    })

    // Save user to database
    return await userRepository.save(newUser);
  } catch(error) {
    if (error instanceof Error) {
      throw new Error(error.message);
    }
    throw new Error('Internal Server Error');
  }
}

// 사용자가 입력한 로그인 정보가 유효한지 확인하는 함수
interface ValidSignInInput {
  email: string;
  password: string;
}
export const validSignInInput = (validProps: ValidSignInInput) => {
  if (!validProps.email || !validProps.password) {
    throw new Error('Email and password are required');
  }
  return;
}

// 사용자 로그인 함수
interface SignInProps {
  email: string;
  password: string;
}
export const signIn = async (signInProps: SignInProps): Promise<{ token: string, user: UserEntity }> => {
  try {
    const findUser = await userRepository.findOne({
      where: { email: signInProps.email }
    });
    if (!findUser) {
      throw new Error('User not found');
    }

    // compare password
    if (!comparePassword({password: signInProps.password, hashedPassword: findUser.password})) {
      throw new Error('Password is incorrect');
    }

    // create Token
    const token = generateToken({userId: findUser.id, role: findUser.role})

    // delete old token 
    await userTokenRepository.delete({ user: findUser });

    // save token to Database
    const userToken = userTokenRepository.create({
      token,
      user: findUser,
      expires_at: new Date(Date.now() + 3600 * 1000),
    });
    await userTokenRepository.save(userToken);

    return { token, user: findUser };
  } catch (error) {
    if (error instanceof Error) {
      throw new Error(error.message);
    }
    throw new Error('Internal Server Error');
  }
}
  • 위 코드의 경우 현재의 Service 코드에서 try/catch로 에러를 핸들링 하고 있는데 이를 리팩토링 하여 반복되고 중복되는 코드를 함수화 할 예정 

함수 작성

// utils/error.ts 

interface HandleErrorProps {
  error: unknown;
  message: string;
}
export const handleError = ({error, message}: HandleErrorProps) => {
  if (error instanceof Error) {
    throw new Error(error.message);
  }
  throw new Error(message);
}

적용 이후 코드

// 사용자 회원가입 함수
interface SignUpProps {
  username: string;
  email: string;
  password: string;
  profile?: string;
}
export const signUp = async (signUpProps : SignUpProps): Promise<UserEntity> => {
  try {
    validSignUpInput(signUpProps);

    const existingUser = await userRepository.findOne({
      where: [
      ]
    });
    if (existingUser) {
      throw new Error('User already exists');
    }

    // Hash password
    const hashedPassword = hashPassword({password: signUpProps.password});

    // Create new user
    const newUser = userRepository.create({
      ...signUpProps,
      password: hashedPassword
    })

    // Save user to database
    return await userRepository.save(newUser);
  } catch(error) {
    handleError({error, message: 'User already exists'});
    throw error
  }
}

// 사용자 로그인 함수
interface SignInProps {
  email: string;
  password: string;
}
export const signIn = async (signInProps: SignInProps): Promise<{ token: string, user: UserEntity }> => {
  try {
    validSignInInput(signInProps);

    const findUser = await userRepository.findOne({
      where: { email: signInProps.email }
    });
    if (!findUser) {
      throw new Error('User not found');
    }

    // compare password
    if (!comparePassword({password: signInProps.password, hashedPassword: findUser.password})) {
      throw new Error('Password is incorrect');
    }

    // create Token
    const token = generateToken({userId: findUser.id, role: findUser.role})

    // delete old token 
    await userTokenRepository.delete({ user: findUser });

    // save token to Database
    const userToken = userTokenRepository.create({
      token,
      user: findUser,
      expires_at: new Date(Date.now() + 3600 * 1000),
    });
    await userTokenRepository.save(userToken);

    return { token, user: findUser };
  } catch (error) {
    handleError({error, message: 'User not found'});
    throw error;
  }
}
  • 이후에 생기는 모든 Service & Controller에서는 해당 함수를 사용하여 에러 핸들링을 하는데 사용할 예정

'Team_Mate > Backend' 카테고리의 다른 글

NodeJS 사용자 정보 조회 기능 구현  (0) 2024.12.22
NodeJS 로그아웃 기능 구현  (1) 2024.12.20
NodeJS 로그인 기능 구현  (0) 2024.12.20
NodeJS 회원가입 기능 구현  (1) 2024.12.20