2025년 1월 14일

김동환·2025년 1월 14일

오늘의 코드

address.service.js 업데이트로 수정했습니다.

import { MESSAGES } from '../constants/message.constant.js';
import addressRepository from '../repositories/address.repository.js';

class AddressService {
  #repository;

  constructor(repository) {
    this.#repository = repository;
  }

  // 주소 생성
  createAddress = async ({ userId, address, addressName }) => {
    if (!userId) {
      throw new Error(MESSAGES.ADDRESS.COMMON.NOT_FOUND_USER);
    }
    if (!address) {
      throw new Error(MESSAGES.ADDRESS.COMMON.ADDRESS.REQUIRED);
    }
    if (!addressName) {
      throw new Error(MESSAGES.ADDRESS.COMMON.ADDRESSNAME.REQUIRED);
    }

    const user = await this.#repository.findUser(userId);
    if (!user) {
      throw new Error(MESSAGES.ADDRESS.COMMON.NOT_FOUND_USER);
    }

    return await this.#repository.createAddress({
      userId,
      address,
      addressName,
    });
  };

  // 주소 찾기
  getAddress = async () => {
    return await this.#repository.getAllAddress();
  };

  // 주소 수정
  updateAddress = async ({ addressId, address, addressName }) => {
    if (!addressId) {
      throw new Error(MESSAGES.ADDRESS.COMMON.NOT_FOUND);
    }
    if (!address) {
      throw new Error(MESSAGES.ADDRESS.COMMON.ADDRESS.REQUIRED);
    }
    if (!addressName) {
      throw new Error(MESSAGES.ADDRESS.COMMON.ADDRESSNAME.REQUIRED);
    }

    const existAddress = await this.#repository.findUnique(addressId);
    if (!existAddress) throw new Error(MESSAGES.ADDRESS.COMMON.NOT_FOUND);

    return await this.#repository.updateAddress({
      addressId,
      address,
      addressName,
    });
  };

  // 주소 삭제
  deleteAddress = async (addressId) => {
    const existAddress = await this.#repository.findUnique(addressId);
    if (!existAddress) throw new Error(MESSAGES.ADDRESS.COMMON.NOT_FOUND);

    return await this.#repository.deleteAddress({
      addressId,
    });
  };

  // 주소 상세 조회
  findAddressById = async (addressId) => {
    const existAddress = await this.#repository.findUnique(addressId);
    if (!existAddress) throw new Error(MESSAGES.ADDRESS.COMMON.NOT_FOUND);

    return await this.#repository.findUnique(addressId);
  };

  // 메인 주소 설정
  setMainAddress = async ({ addressId, userId }) => {
    const existingMainAddresses =
      await this.#repository.getMainAddresses(userId);

    // 데이터 무결성 검증: 중복된 mainAddress가 있을 경우 정리
    if (existingMainAddresses.length > 1) {
      throw new Error(MESSAGES.ADDRESS.MAINADDRESS.SAME_ADDRESS);
    }

    return await this.#repository.setMainAddress({ addressId, userId });
  };
}

export default new AddressService(addressRepository);

오늘의 학습 (TIL - Today I Learned)


주제: 주소 관리 서비스 (AddressService) 코드 작성


배운 점

오늘은 JavaScript로 작성된 AddressService 클래스 코드를 분석하고 이해했습니다. 이 클래스는 주소 관리 기능을 제공하며, 아래와 같은 주요 메서드들로 구성되어 있습니다.


1. 클래스 구조

  • AddressService 클래스는 주소 관리 관련 로직을 구현하고 있으며, 생성자에서 repository 객체를 주입받아 의존성을 관리합니다.
  • 이 클래스는 address.repository.js에 정의된 데이터 처리 로직을 사용합니다.

2. 주요 메서드와 동작

1) 주소 생성 (createAddress)

  • 기능: 사용자가 입력한 userId, address, addressName을 기반으로 주소를 생성합니다.
  • 유효성 검증:
    • userId, address, addressName이 필수로 제공되지 않으면 에러를 발생시킵니다.
    • userId에 해당하는 사용자가 존재하지 않으면 에러를 발생시킵니다.
  • 데이터 처리: repository.createAddress 메서드를 호출하여 새 주소를 저장합니다.

2) 주소 조회 (getAddress)

  • 기능: 모든 주소 데이터를 조회합니다.
  • 데이터 처리: repository.getAllAddress 메서드를 호출하여 주소 목록을 반환합니다.

3) 주소 수정 (updateAddress)

  • 기능: 특정 addressId에 해당하는 주소를 수정합니다.
  • 유효성 검증:
    • addressId, address, addressName이 필수로 제공되지 않으면 에러를 발생시킵니다.
    • addressId에 해당하는 주소가 존재하지 않으면 에러를 발생시킵니다.
  • 데이터 처리: repository.updateAddress 메서드를 호출하여 주소를 수정합니다.

4) 주소 삭제 (deleteAddress)

  • 기능: 특정 addressId에 해당하는 주소를 삭제합니다.
  • 유효성 검증:
    • addressId에 해당하는 주소가 존재하지 않으면 에러를 발생시킵니다.
  • 데이터 처리: repository.deleteAddress 메서드를 호출하여 주소를 삭제합니다.

5) 주소 상세 조회 (findAddressById)

  • 기능: 특정 addressId에 해당하는 주소의 상세 정보를 조회합니다.
  • 유효성 검증:
    • addressId에 해당하는 주소가 존재하지 않으면 에러를 발생시킵니다.
  • 데이터 처리: repository.findUnique 메서드를 호출하여 주소 상세 정보를 반환합니다.

6) 메인 주소 설정 (setMainAddress)

  • 기능: 특정 userId와 연결된 주소 중 하나를 메인 주소로 설정합니다.
  • 유효성 검증:
    • 동일 사용자(userId)에 대해 중복된 메인 주소가 존재하지 않도록 처리합니다.
    • 메인 주소가 2개 이상 존재하면 에러를 발생시킵니다.
  • 데이터 처리: repository.setMainAddress 메서드를 호출하여 메인 주소를 설정합니다.

3. 배운 교훈

  1. 유효성 검증의 중요성

    • 사용자 입력값을 처리하기 전에 필요한 데이터를 검증하여 예상치 못한 오류를 방지할 수 있습니다.
    • 이 코드에서는 각 메서드의 입력값과 데이터 존재 여부를 철저히 확인하고 있습니다.
  2. 레포지토리 패턴 사용

    • 데이터베이스 작업을 담당하는 레포지토리 레이어를 통해 비즈니스 로직과 데이터 처리 로직을 분리할 수 있습니다.
    • 이를 통해 코드의 가독성과 유지보수성이 향상됩니다.
  3. 에러 메시지 관리

    • MESSAGES 객체를 사용하여 에러 메시지를 관리함으로써, 코드 전반에서 일관성 있는 에러 메시지를 제공합니다.

4. 앞으로의 활용 방안

  • 이 구조를 바탕으로 다른 서비스 클래스도 유사하게 작성할 수 있을 것 같습니다.
  • 테스트 코드를 추가하여 각 메서드의 동작을 검증하고, 오류 상황에 대한 예외 처리도 강화할 계획입니다.

위 코드를 통해 서비스 로직과 레포지토리 패턴에 대한 이해를 깊이 할 수 있었습니다.


address.repository.js 수정

import { prisma } from './../utils/prisma/index.js';

class AddressRepository {
  #orm;

  constructor(orm) {
    this.#orm = orm;
  }

  // 주소 생성
  createAddress = async ({ address, addressName, userId }) => {
    return await this.#orm.address.create({
      data: {
        userId,
        address,
        addressName,
      },
    });
  };

  // 주소 조회
  getAllAddress = async () => {
    return await this.#orm.address.findMany();
  };

  // 주소 수정
  updateAddress = async ({ addressId, address, addressName }) => {
    console.log(addressId);
    return await this.#orm.address.update({
      where: {
        addressId,
      },
      data: {
        address: address,
        addressName: addressName,
      },
    });
  };

  // 주소 삭제
  deleteAddress = async ({ addressId }) => {
    return await this.#orm.address.delete({
      where: { addressId },
    });
  };

  // 주소 찾기
  findUnique = async (addressId) => {
    return await this.#orm.address.findUnique({ where: { addressId } });
  };

  // 유저 찾기
  findUser = async (userId) => {
    return await this.#orm.user.findUnique({
      where: { userId },
    });
  };

  // 메인 주소 설정
  setMainAddress = async ({ addressId, userId }) => {
    // 1. 기존 메인 주소 비활성화
    await this.#orm.address.updateMany({
      where: { userId, mainAddress: true },
      data: { mainAddress: false },
    });

    // 2. 지정된 주소를 메인 주소로 설정
    return await this.#orm.address.update({
      where: { addressId },
      data: { mainAddress: true },
    });
  };

  // Repository 메서드: 특정 사용자의 mainAddress가 true인 주소들을 조회
  getMainAddresses = async (userId) => {
    return await this.#orm.address.findMany({
      where: {
        userId, // 특정 사용자
        mainAddress: true, // mainAddress가 true인 항목만
      },
    });
  };
}

export default new AddressRepository(prisma);

오늘의 학습 (TIL - Today I Learned)


주제: 주소 관리 레포지토리 (AddressRepository) 코드 작성


배운 점

오늘은 Prisma를 활용해 주소 관리 관련 데이터베이스 작업을 담당하는 AddressRepository 클래스를 분석하고 이해했습니다. 이 클래스는 주소와 관련된 다양한 CRUD 작업을 구현하고 있으며, 다음과 같은 주요 메서드로 구성되어 있습니다.


1. 클래스 구조

  • AddressRepository 클래스는 데이터베이스 작업을 처리하며, 생성자에서 ORM 객체(prisma)를 주입받아 데이터베이스와 상호작용합니다.
  • Prisma ORM을 사용하여 간결하면서도 효율적인 쿼리를 작성했습니다.

2. 주요 메서드와 동작

1) 주소 생성 (createAddress)

  • 기능: 사용자가 입력한 주소(address), 주소 이름(addressName), 사용자 ID(userId)를 데이터베이스에 저장합니다.
  • 데이터 처리:
    • prisma.address.create 메서드를 호출하여 새 주소를 생성합니다.

2) 주소 조회 (getAllAddress)

  • 기능: 모든 주소 데이터를 조회합니다.
  • 데이터 처리:
    • prisma.address.findMany 메서드를 호출하여 주소 목록을 반환합니다.

3) 주소 수정 (updateAddress)

  • 기능: 특정 addressId에 해당하는 주소 데이터를 수정합니다.
  • 데이터 처리:
    • prisma.address.update 메서드를 사용하여 주소와 주소 이름을 업데이트합니다.
  • 로깅 추가:
    • addressId 값을 로그로 출력하여 디버깅을 용이하게 합니다.

4) 주소 삭제 (deleteAddress)

  • 기능: 특정 addressId에 해당하는 주소 데이터를 삭제합니다.
  • 데이터 처리:
    • prisma.address.delete 메서드를 호출하여 해당 주소를 삭제합니다.

5) 주소 상세 조회 (findUnique)

  • 기능: 특정 addressId에 해당하는 주소 데이터를 조회합니다.
  • 데이터 처리:
    • prisma.address.findUnique 메서드를 호출하여 주소 데이터를 반환합니다.

6) 유저 조회 (findUser)

  • 기능: 특정 userId에 해당하는 사용자 데이터를 조회합니다.
  • 데이터 처리:
    • prisma.user.findUnique 메서드를 호출하여 사용자 데이터를 반환합니다.

7) 메인 주소 설정 (setMainAddress)

  • 기능: 특정 사용자의 주소 중 하나를 메인 주소로 설정합니다.
  • 단계적 처리:
    1. 기존 메인 주소를 모두 비활성화:
      • prisma.address.updateMany 메서드를 호출하여 특정 사용자의 mainAddress 값을 false로 업데이트합니다.
    2. 지정된 주소를 메인 주소로 활성화:
      • prisma.address.update 메서드를 호출하여 해당 주소의 mainAddress 값을 true로 설정합니다.

8) 메인 주소 조회 (getMainAddresses)

  • 기능: 특정 사용자의 메인 주소(mainAddress: true) 목록을 조회합니다.
  • 데이터 처리:
    • prisma.address.findMany 메서드를 호출하여 메인 주소 데이터를 반환합니다.

3. 배운 교훈

  1. Prisma를 활용한 데이터베이스 작업

    • Prisma의 간단하고 직관적인 API를 통해 복잡한 쿼리 작업을 효율적으로 처리할 수 있습니다.
    • findUnique, findMany, update, delete 등의 메서드를 사용해 다양한 CRUD 작업을 구현했습니다.
  2. 비즈니스 로직과 데이터 로직 분리

    • 데이터베이스와 상호작용하는 로직을 별도의 레포지토리 클래스로 분리하여 비즈니스 로직(AddressService)과의 의존성을 줄였습니다.
    • 이를 통해 코드의 재사용성과 유지보수성이 크게 향상됩니다.
  3. 단계적 데이터 처리

    • setMainAddress 메서드에서 기존 데이터를 먼저 정리한 후 새로운 데이터를 설정하는 방식으로 데이터 무결성을 유지했습니다.

4. 앞으로의 활용 방안

  • 레포지토리 레이어를 통해 데이터베이스 작업을 더 체계적으로 관리할 수 있다는 점을 알게 되었습니다.
  • 복잡한 데이터 처리 로직이 필요한 다른 서비스에도 이와 같은 구조를 적용할 수 있을 것입니다.
  • 테스트 코드를 추가하여 각 메서드의 정확성을 검증하고, 오류 상황에 대한 대응 로직을 강화할 계획입니다.

이번 코드를 통해 Prisma ORM과 레포지토리 패턴을 활용한 데이터 처리에 대한 이해를 깊이할 수 있었습니다.

profile
Node.js 7기

0개의 댓글