2025년 1월 15일

김동환·2025년 1월 15일

오늘의 코드

import { HTTP_STATUS } from '../constants/http-status.constant.js';
import { MESSAGES } from '../constants/message.constant.js';
import addressService from '../services/address.service.js';

class AddressController {
  #service;

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

  // 주소 생성
  createAddress = async (req, res, next) => {
    try {
      const { address, addressName } = req.body;
      // const userId = 1;
      const { userId } = req.user;
      const _address = await this.#service.createAddress({
        userId: +userId,
        address,
        addressName,
      });
      return res.status(HTTP_STATUS.CREATED).json({
        status: HTTP_STATUS.CREATED,
        message: MESSAGES.ADDRESS.CREATE.SUCCEED,
        data: _address,
      });
    } catch (error) {
      console.error(MESSAGES.ADDRESS.CREATE.NOT_ERROR, error);
      res
        .status(HTTP_STATUS.BAD_REQUEST)
        .json({ message: MESSAGES.ADDRESS.CREATE.NO_BODY_DATA });
    }
  };

  // 주소 조회
  getAddress = async (req, res, next) => {
    try {
      const _address = await this.#service.getAddress();
      return res.status(HTTP_STATUS.OK).json({
        status: HTTP_STATUS.OK,
        message: MESSAGES.ADDRESS.READ_LIST.SUCCEED,
        data: _address,
      });
    } catch (error) {
      console.error(MESSAGES.ADDRESS.READ_LIST.NOT_ERROR, error);
      res
        .status(HTTP_STATUS.BAD_REQUEST)
        .json({ message: MESSAGES.ADDRESS.READ_LIST.NO_BODY_DATA });
    }
  };

  // 주소 수정
  updateAddress = async (req, res, next) => {
    try {
      const { addressId } = req.params;
      const { address, addressName } = req.body;

      const _address = await this.#service.updateAddress({
        addressId: +addressId,
        address: address,
        addressName: addressName,
      });
      return res.status(HTTP_STATUS.OK).json({
        status: HTTP_STATUS.OK,
        message: MESSAGES.ADDRESS.UPDATE.SUCCEED,
        data: _address,
      });
    } catch (error) {
      console.error(MESSAGES.ADDRESS.UPDATE.NOT_ERROR, error);
      res
        .status(HTTP_STATUS.BAD_REQUEST)
        .json({ message: MESSAGES.ADDRESS.UPDATE.NO_BODY_DATA });
    }
  };

  // 주소 삭제
  deleteAddress = async (req, res, next) => {
    try {
      const { addressId } = req.params;

      const _address = await this.#service.deleteAddress(+addressId);

      return res.status(HTTP_STATUS.OK).json({
        status: HTTP_STATUS.OK,
        message: MESSAGES.ADDRESS.DELETE.SUCCEED,
        data: _address,
      });
    } catch (error) {
      console.error(MESSAGES.ADDRESS.DELETE.NOT_ERROR, error);
      res
        .status(HTTP_STATUS.INTERNAL_SERVER_ERROR)
        .json({ message: error.message });
    }
  };

  // 주소 상세 조회
  findAddressById = async (req, res, next) => {
    try {
      const { addressId } = req.params;

      const _address = await this.#service.findAddressById(+addressId);

      return res.status(HTTP_STATUS.OK).json({
        status: HTTP_STATUS.OK,
        message: MESSAGES.ADDRESS.READ_LIST.SUCCEED,
        data: _address,
      });
    } catch (error) {
      console.error(MESSAGES.ADDRESS.READ_LIST.NOT_ERROR, error);
      res
        .status(HTTP_STATUS.INTERNAL_SERVER_ERROR)
        .json({ message: error.message });
    }
  };

  // 메인 주소 설정
  setMainAddress = async (req, res, next) => {
    try {
      const { addressId } = req.params;
      const { userId } = req.user;

      const _address = await this.#service.setMainAddress({
        addressId: +addressId,
        userId: +userId,
      });

      return res.status(HTTP_STATUS.OK).json({
        status: HTTP_STATUS.OK,
        message: MESSAGES.ADDRESS.UPDATE.SUCCEED,
        data: _address,
      });
    } catch (error) {
      console.error(MESSAGES.ADDRESS.MAINADDRESS.NOT_ERROR, error);
      res
        .status(HTTP_STATUS.BAD_REQUEST)
        .json({ message: MESSAGES.ADDRESS.DELETE.NO_BODY_DATA });
    }
  };
}

export default new AddressController(addressService);

TIL (Today I Learned): AddressController 코드 리뷰

오늘은 AddressController에 대한 코드를 살펴보며 해당 코드의 구조와 동작 원리에 대해 학습했습니다. 아래는 주요 내용을 정리한 것입니다.


1. 코드 구조

AddressController는 주소와 관련된 CRUD 및 특정 기능(메인 주소 설정)을 담당하는 클래스입니다. RESTful API의 컨트롤러 역할을 하며, 주요 메서드로는 다음과 같은 기능이 구현되어 있습니다.

  • 주소 생성 (createAddress)

    • 요청 본문에서 사용자 ID, 주소, 주소 이름을 받아 주소를 생성합니다.
    • 성공 시 생성된 주소 데이터를 반환하고, 실패 시 에러 메시지를 반환합니다.
  • 주소 조회 (getAddress)

    • 모든 주소 데이터를 조회합니다.
    • 성공 시 조회된 주소 리스트를 반환하고, 실패 시 에러 메시지를 반환합니다.
  • 주소 수정 (updateAddress)

    • 특정 주소 ID에 대해 요청 본문에서 전달된 데이터로 수정합니다.
    • 성공 시 수정된 주소 데이터를 반환하며, 실패 시 에러 메시지를 반환합니다.
  • 주소 삭제 (deleteAddress)

    • 특정 주소 ID를 삭제합니다.
    • 성공 시 삭제된 데이터를 반환하며, 실패 시 에러 메시지를 반환합니다.
  • 주소 상세 조회 (findAddressById)

    • 특정 주소 ID에 대한 상세 정보를 조회합니다.
    • 성공 시 해당 주소 데이터를 반환하며, 실패 시 에러 메시지를 반환합니다.
  • 메인 주소 설정 (setMainAddress)

    • 특정 주소 ID를 메인 주소로 설정합니다.
    • 성공 시 설정된 주소 데이터를 반환하며, 실패 시 에러 메시지를 반환합니다.

2. 특징

  1. 의존성 주입
    AddressController는 생성자를 통해 의존성을 주입받습니다. 이는 테스트와 유지보수를 쉽게 해주는 좋은 패턴입니다.

  2. 상태 코드와 메시지 관리

    • HTTP 상태 코드와 메시지를 별도의 상수 파일로 관리합니다.
    • HTTP_STATUSMESSAGES 상수를 활용하여 코드 가독성과 유지보수성을 높였습니다.
  3. 에러 처리

    • 각 메서드에서 try-catch 구문을 통해 예외를 처리하며, 에러 로그를 남기고 적절한 상태 코드와 메시지를 반환합니다.
  4. 비공개 멤버(#)

    • 서비스(#service) 멤버 변수를 #을 사용하여 비공개로 설정함으로써 캡슐화를 준수했습니다.

3. 아쉬운 점 및 개선 사항

  1. 중복 코드 제거

    • 에러 처리 구문에서 try-catch와 응답 구조가 유사하므로, 이를 공통화하는 유틸리티 함수를 도입할 수 있습니다.
  2. 데이터 유효성 검사

    • 요청 본문에서 필수 값(address, addressName, addressId)에 대한 유효성 검사가 컨트롤러 레벨에서 빠져 있습니다.
    • 이를 추가하거나, middleware를 활용하여 사전 검증을 도입할 필요가 있습니다.
  3. HTTP 상태 코드와 메시지 매핑

    • 현재 코드에서는 일부 메서드가 상태 코드와 메시지 매핑이 일관되지 않습니다. 예를 들어, 삭제 실패 시 INTERNAL_SERVER_ERROR를 반환하기보다는 NOT_FOUND 또는 BAD_REQUEST가 더 적절할 수 있습니다.
  4. 로깅 개선

    • 단순한 console.error 대신 로깅 라이브러리(e.g., Winston, Bunyan)를 사용하여 로그 수준과 출력 포맷을 체계적으로 관리할 수 있습니다.

4. 배운 점

  • 클래스 기반의 컨트롤러 설계 및 의존성 주입의 중요성을 학습했습니다.
  • 상수 파일로 상태 코드와 메시지를 관리하면 코드 유지보수가 훨씬 수월하다는 것을 확인했습니다.
  • 공통 기능(에러 처리, 응답 구조 등)을 유틸리티 함수로 추출하여 중복을 줄이는 것이 필요함을 알게 되었습니다.

이 코드는 RESTful API 컨트롤러를 설계할 때의 기본적인 모범 사례를 보여줍니다. 앞으로 비슷한 구조의 코드를 작성할 때 유용한 참고 자료가 될 것입니다.

profile
Node.js 7기

0개의 댓글