고급 프로젝트 <CODI-IT> 개별 개발 리포트

코드잇
이 글은 읽는데 약 8분이 걸립니다.

1. 프로젝트 개요

본 프로젝트는 패션 이커머스 플랫폼의 웹 서비스 개발과 구축을 목표로 하였습니다. 기본적으로 오픈마켓 형태의 시스템을 갖으며, 판매자와 구매자 두 역할로 나뉩니다. 판매자는 자신만의 상점을 개설하고 상품을 등록, 관리할 수 있으며, 구매자는 상품을 구매하고 리뷰를 작성하는 등의 역할을 수행합니다.

프로젝트를 진행하면서 주로 문의(Inquiry)와 리뷰(Review 작성) API 서비스 로직 작성 및 CI/CD 파이프라인 구축을 담당하였으며, 가독성 및 유지보수성이 좋은 코드 품질 유지을 위해 노력했습니다.

  • 프로젝트명: CODI-IT
  • 기간: 2025년 12월 1일(기획) ~ 2026년 1월 13일(최종 발표)
  • 담당 역할:
    • 핵심 백엔드 로직 일부: 리뷰(Review) 및 문의(Inquiry) 시스템 전담 개발
    • 데브옵스: Docker 컨테이너화 및 GitHub Actions 기반 CI/CD 파이프라인 구축
    • DB 설계: Prisma Schema 설계 및 마이그레이션 관리
  • 참조

2. 기술 스택

  • 언어 및 프레임워크: TypeScript, Node.js, Express.js
  • DBMS / ORM: AWS RDS, PostgreSQL, Prisma ORM
  • Infrastructure: Docker, Docker Compose, Nginx
  • CI/CD: GitHub Actions, GHCR, AWS EC2
  • Tooling: Prettier, ESLint

3. 핵심 구현 기능

리뷰 시스템

단순한 CRUD를 넘어, 데이터 무결성과 비즈니스 로직의 정합성을 최우선으로 구현했습니다.

  • 구매 검증 로직: fetchOrderItem을 통해 실제 상품을 구매한 유저만 리뷰를 작성할 수 있도록 검증하여 가짜 리뷰를 원천 차단
  • 중복 방지: checkReviewExists 로직을 통해 주문 상품 하나당 하나의 리뷰만 작성되도록 제한, 데이터 중복을 방지
  • 권한 제어: 본인의 주문 내역에 대해서만 접근 가능하도록 Service 계층에서 철저한 권한 검증(Authorization)을 수행
export const createReview = async (
  params: CreateReviewParamsDto,
): Promise<CreateReviewResponseDto> => {
  const { productId, userId, data } = params;

  // 주문 내역 유효성 검사 (구매 여부 및 본인 확인)
  const orderItem = await reviewRepository.fetchOrderItem(data.orderItemId);

  if (!orderItem) {
    throw new HttpError('주문 내역을 찾을 수 없습니다.', 404);
  }
  if (orderItem.productId !== productId) {
    throw new HttpError('해당 상품에 대한 주문 내역이 아닙니다.', 400);
  }
  if (orderItem.order.userId !== userId) {
    throw new HttpError(
      '본인의 주문 내역에 대해서만 리뷰를 작성할 수 있습니다.',
      403,
    );
  }

  // 중복 리뷰 검사
  const reviewExists = await reviewRepository.checkReviewExists(
    data.orderItemId,
  );
  if (reviewExists) {
    throw new HttpError('이미 해당 주문 내역에 대한 리뷰를 작성했습니다.', 409);
  }

  // 리뷰 작성
  const createdReview = await reviewRepository.createReview(params);

  if (!createdReview) {
    throw new HttpError('리뷰 작성에 실패했습니다.', 500);
  }

  return createdReview;
};
문의 시스템

구매자와 판매자 간의 원활한 소통을 위해 보안(비밀글)과 알림 기능이 결합된 문의 시스템을 구축했습니다.

  • 비밀글 로직: isSecret 플래그를 도입하여, 작성자와 해당 스토어 판매자 외에는 내용을 볼 수 없도록 Row-Level Security에 준하는 로직을 애플리케이션 레벨에서 구현
  • 판매자 답변 및 알림 연동: 판매자가 답변을 등록하면, 즉시 NotificationService와 연동하여 구매자에게 알림이 발송되는 이벤트 기반 설계를 적용
  • 원자적 트랜잭션 처리: 문의 답변 등록 시 Prisma 트랜잭션을 적용하여, 답변 생성과 문의 상태 변경(답변완료) 두 가지 작업이 반드시 동시에 성공하거나 실패하도록 보장
  • 쿼리 최적화: include 대신 중첩 select 방식을 채택하여, 연관된 테이블에서 불필요한 필드는 제외하고 필요한 데이터만 조회함으로써 DB 부하를 줄이고 응답 속도를 개선
CI/CD & Docker

개발 생산성 향상과 안정적인 배포를 위해 CI/CD 환경을 구축하였습니다.

  • Docker Multi-stage Build: builder 스테이지와 production 스테이지를 분리하여, 빌드 도구를 제외한 경량화된 프로덕션 이미지를 생성 (용량 최적화)
  • GitHub Actions CI/CD:
    • CI: GitHub에서 Push 이벤트 살생 시 Formatting → Type Check → Build 과정을 자동화하여 코드 품질을 일관되게 보장
    • CD: Docker 이미지를 빌드하여 GHCR에 푸시하고, EC2 서버에서 docker-compose를 통해 자동 배포를 구현

4. 기술적 성과 및 문제 해결

서비스 계층 분리를 통한 유지보수성 향상
  • 문제: 컨트롤러에 비즈니스 로직이 집중될 경우, 코드 중복과 테스트 어려움 발생 우려
  • 해결: 3-Layer Architecture (Controller – Service – Repository)를 엄격히 적용
    • Repository는 Prisma를 사용한 순수 DB 접근만 담당 (fetchReviewDetailById 등)
    • Service는 비즈니스 검증 로직만 담당 (validateUser, checkSecretAccess 등)
  • 성과: 코드의 책임이 명확해져 팀원들이 내 코드를 참조하기 쉬워졌으며, 유지보수가 용이한 구조를 완성
DTO를 활용한 타입 안정성 확보
  • 성과: ReviewDetailParamsDto, CreateInquiryParamsDto 등 명확한 DTO를 정의하여, 프론트엔드에서 넘어오는 데이터의 타입을 런타임 이전에 컴파일 타임에서 보장받아 런타임 에러를 획기적으로 경감
인프라 구축으로 팀 개발 효율 증대
  • 성과: 로컬에서는 docker-compose로 DB와 앱을 한 번에 실행하고, 배포 시에는 GitHub Actions가 자동으로 수행되게 함으로써 팀원들이 배포가 아닌 개발에만 집중할 수 있는 환경을 제공

5. 코드 품질 및 협업

  • 일관된 에러 처리: HttpError 클래스를 공통으로 사용하여, 여러 HTTP Status Code를 의미론적으로 정확하게 반환하도록 구현
  • Prettier & Linting: CI 파이프라인에 프맷팅 체크를 강제하여, 5명의 팀원이 작성한 코드가 마치 한 명이 작성한 것처럼 일관된 스타일을 유지하도록 함

6. 향후 개선 사항

  • 테스트 코드 커버리지: 현재 CI 파이프라인에 npm test 단계가 주석 처리되어 있는데, 향후 Jest 등을 활용한 Unit Test를 추가하여 비즈니스 로직의 안정성을 더욱 강화하고 싶습니다.
  • 트랜잭션 관리 고도화: 현재는 단일 모델 업데이트가 주를 이루지만, 추후 ‘리뷰 작성 시 포인트 적립’과 같이 두 개 이상의 테이블을 동시에 수정해야 할 경우 Prisma의 Interactive Transactions를 적용하여 데이터 정합성을 더욱 견고히 할 예정입니다.
  • 캐싱 도입: 리뷰 조회가 빈번한 인기 상품의 경우, Redis 등 인-메모리 캐싱 시스템을 도입하여 조회 성능을 최적화할 여지가 있습니다.
  • 무중단 배포 도입: 현재 CI/CD 파이프라인에서 배포를 자동화하고는 있지만, 새롭게 Pull 받은 이미지로 갱신하기 위해 docker-compose로 실행 중인 컨테이너를 단순히 restart하고 있습니다. 추후 Rolling, Blue/Green, Canary 등의 아키텍처를 도입하여 무중단 배포를 구현하고 싶습니다.

7. 프로젝트 회고

이번 프로젝트에서 리뷰와 문의, 그리고 CI/CD라는 핵심 도메인을 설계부터 구현까지 주도적으로 수행하며, 데이터의 흐름과 무결성을 지키는 백엔드 개발의 책임감을 배울 수 있었습니다. 특히 Docker와 GitHub Actions를 통한 CI/CD 파이프라인 도입은 이번 프로젝트에서 처음 시도해본 것인데, 이를 직접 구축하여 팀 전체의 개발 사이클을 효율화시킨 경함은 큰 자산이 되었습니다.

그러나 팀원 간 커뮤니케이션이 좀 더 활발하게 이루어졌더라면, 전체 개발 일정의 단축과 추가 기능 도입까지 이룰 수 있었을 것이라는 아쉬움도 남습니다.

이번 프로젝트는 비즈니스 로직 구현 능력과 인프라 핸들링 능력을 동시에 배우고 익힐 수 있었던 뜻깊은 시간이었습니다.