👯‍♀️ 프로젝트 회고/[Team] Cobra09 - 공동 구매 마켓 프로젝트

[프로젝트] 공동구매 마켓 프로젝트 최종 회고

수댕ʕت̫͡ʔ 2025. 1. 7. 14:49

🛒 개발 과정

Node.js를 공부하고 백엔드의 역할을 맡아 공동 구매 쇼핑몰 프로젝트 개발에 참여했다.

API 설계, DB 설계가 프로젝트를 하다보니 새롭게 느껴졌다. 이 프로젝트를 통해서 DB 개념의 중요성과 API 에 대해 많은 공부를 할 수 있었다.

1) 주제

누구나 공동구매를 주선할 수 있고, 물품을 구매할 수 있는 공동 구매 플랫폼

2) 개발 인원

풀스택 : 1명

백엔드 : 2명

프론트엔드 : 2명

🙋‍♀️ 내가 구현한 기능

백엔드

  • ERD 설계
  • API 명세서 작성
  • 찜 기능
  • 마이페이지 (개인 정보 수정/ 조회, 판매 내역, 주선 내역, 찜 내역 조회)

💻 결과

1) ERD

erd 관계 설계하는데 어려움이 많았다. 그래서 프로젝트 마친 후, 리팩토링을 통해 ERD 관계 설정을 아래와 같이 수정했다.

2) API 명세서

다음과 같이 노션을 이용해서 API 명세서를 작성하고 개발했다.

노션

 

⚽ 트러블 슈팅

1️⃣ 데이터 삽입과 참조 무결성 (Foreign Key Constraint)

처음에 MySQL에 테이블을 생성하고 테스트를 위해 order_item 테이블에 데이터를 삽입하려고했다. 근데 아래와 같은 에러가 발생했다.

Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails

 

구글링을 해보니 참조 무결성을 위반한 것이었다. 참조 무결성은 기본키와 참조 키 간의 관계가 항상 일관되게 유지되도록 보장하는 것이다. 

문제를 자세하게 살펴보면 Product & Order_item 테이블의 관계를 알아야 한다.

-- Product 테이블 생성
CREATE TABLE Product (
    product_key INT AUTO_INCREMENT PRIMARY KEY, -- 판매 물품 ID (Primary Key)
    name VARCHAR(255) NOT NULL, -- 물품 이름
    deadline DATE NOT NULL, -- 판매 마감 기한
    price INT NOT NULL, -- 판매 가격
    max_quantity INT NOT NULL, -- 판매 가능 최대 수량
    image VARCHAR(255) NOT NULL, -- 물품 이미지 경로
    category_id INT NOT NULL, -- 카테고리 ID (Foreign Key)
    user_id INT NOT NULL, -- 주선자 사용자 ID (Foreign Key)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 생성일
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 수정일
    FOREIGN KEY (category_id) REFERENCES Category (category_id) ON DELETE CASCADE, -- 카테고리 참조
    FOREIGN KEY (user_id) REFERENCES User (user_id) ON DELETE CASCADE -- 주선자 참조
);


-- Order_item 테이블 생성
CREATE TABLE Order_item (
    order_item_id INT AUTO_INCREMENT PRIMARY KEY, -- 주문 아이템 ID (Primary Key)
    product_key INT NOT NULL, -- 주문한 물품 ID (Foreign Key)
    user_id INT NOT NULL, -- 주문자 사용자 ID (Foreign Key)
    quantity INT NOT NULL, -- 주문 수량
    address VARCHAR(255) NOT NULL, -- 주문자 주소
    phone VARCHAR(20) NOT NULL, -- 주문자 전화번호
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 생성일
    FOREIGN KEY (product_key) REFERENCES Product (product_key) ON DELETE CASCADE, -- 물품 참조
    FOREIGN KEY (user_id) REFERENCES User (user_id) ON DELETE CASCADE -- 사용자 참조
);

 

여기서  Order_item 테이블은 Product의 product_key를 참조하고 있다. 

그렇기 때문에 Order_item에 데이터를 삽입하려면 Product 테이블에 product_key를 확인하고 데이터를 삽입해야하는 것이다.

 

예를 들어, Product 테이블에 다음과 같은 데이터가 담겨있다. 

product_key name deadline price max_quantity image category_id user_id
1 맥북 2024-12-31 10000 50 image1.jpg 2 1
2 딸기 2024-12-31 15000 30 image2.jpg 3 2

 

근데 내가 Order_item 테이블에 이렇게 데이터를 삽입하면 참조 무결성이 위반된다..! 왜냐면 product_key에 3은 Product 테이블에 존재하지 않기 때문이다. 

order_item_id product_key user_id quantity address phone created_at
1 3 2 2 Seoul, Korea 010-1234-5678 2024-12-14 12:05

 

2️⃣ 중첩 조인과 데이터 가공

마이페이지에 해당하는 API를 개발하며 중첩 조인 시 클라이언트에게 어떤 방식으로 데이터를 제공해야하는지 어려웠다.

데이터가 객체 형태로 조인되어있기 때문에 클라이언트가 필요한 데이터만 가공해 전달하는것이 베스트라는 것을 배웠다.

그래서 객체의 형태를 열심히 파악하고 아래와 같이 클라이언트에게 이미지에 대한 정보 데이터를 보냈다.

const images = user.Order_items.map((item) => item.product.image) || [];  // ["image1.jpg", "image2.jpg"]

 

3️⃣ 식별관계와 비식별관계

ERD 그래프를 그리는데 식별관계와 비식별관계의 개념이 헷갈리기 시작했다. erdcloud로 그래프를 그리면서 핑크색 키와 파란색 키가 존재하는데 여기서 차이점은 식별관계와 비식별관계라고 한다.

 

식별관계와 비식별관계의 개념은 다음과 같다. 

식별관계 : 부모 테이블의 기본키 또는 유니크 키를 자식 테이블이 자신의 키본키로 사용하는 관계. 반드시 부모 테이블에 존재해야만 자식 테이블에 데이터를 추가할 수 있다.
비식별관계 : 부모 테이블의 기본키 또는 유니크 키를 기본키로 사용하지 않고, 외래키로 사용하는 관계. 부모 데이터가 없어도 자식 테이블에서 데이터를 추가할 수 있다.

 

하지만 우리는 테이블 관계를 설정할때 부모 테이블의 기본키를 외래키로 사용해서 비식별관계! 라고 처음에 생각했지만 생각해보니 우리는 테이블을 cascade로 설정했다. 이 때부터 혼란이 오기 시작했다... 근데 내가 잘못 알고 있었던 부분은 cascade 설정은 식별관계나 비식별관계와 직접적인 관련이 없다고 한다. cascade는 테이블 간 참조 무결성을 유지하기 위한 것 뿐이고, 관계 유형을 결정하지 않는다고 한다.  

 

ERD를 설계할 때는 프로젝트의 기능을 잘 파악하고 어떤 방법이 좋을지 판단해 사용하는 것이다. 근데 보통 식별관계보다 비식별관계를 더 유리하다고 한다. 그 이유는 부모 테이블과의 의존성을 제거하는 것이 좋기 때문이다.