[오름캠프] 두번째 미니프로젝트 후기

baaanjy·2025년 1월 11일

⛺️ 오름캠프

목록 보기
4/4
post-thumbnail

✍️ 오름캠프 프론트엔드 3기 두번째 미니프로젝트 회고

⚠️ 구구절절 주의 ⚠️

✔️ 프로젝트 소개 🏊

주제

수영복 쇼핑몰
Swim360 🔗
GitHub Repository 🔗

일정

총 기간: 4주(12/2~12/27)

  • 1주차: 기획 및 디자인
  • 2주차: UI 개발 및 백엔드 설계
  • 3주차: 기능 개발
  • 4주차: 오류 점검 및 발표

팀

팀명: KBS-WIN(케이비스윈), 총 4인 구성
나의 담당

  • 메인페이지: 헤더, 푸터, 무한 배너 캐러셀, 베스트 상품 캐러셀
  • 마이페이지: 회원정보 수정, 리뷰 및 포인트 상세내역
  • 로그인 및 로그아웃

그리고.. 팀장역할도 맡게 되었다.

✔️ 기술스택

프로젝트 요구사항

React를 사용할 것, 백엔드는 자유이나 사용할 경우 Node.js 또는 Deno에 기반한 코드만 사용할 것, 타입스크립트는 필수는 아니나 권장
우리 팀은 현업에서 많이 사용되는지를 중점을 두었고, 그 외에는 학습한 것을 위주로 선택했다.

Frontend

Backend

✔️ 서비스 주요 기능

쇼핑몰의 주요 기능들을 모두 구현하고, 추가적으로 3D 구현까지 진행했다.

  • 메인 페이지: 백그라운드에서 동영상 재생, 홍보 이미지 무한 캐러셀, 판매량으로 상품 정렬하여 베스트 상품을 캐러셀로 구성
  • 카테고리: 여성 수영복, 남성수영복, 악세사리로 구성, 호버시 하위 카테고리 표시
  • 상품 목록: 선택된 카테고리를 표시, 상품에 마우스 호버시 이미지 변경
  • 상품 상세: 옵션 및 수량 선택, 구매와 장바구니로 이동, 상품을 3D 이미지로 제공(Orbitcontrol 가능), 리뷰 목록 및 리뷰 상세 내용 확인
  • 장바구니: 장바구니에서 상품 삭제, 선택된 상품 구매
  • 구매: 주문 내용 입력 및 완료, 주소 찾기 api 연동
  • 로그인 및 로그아웃: sesseionStorage로 로그인 및 로그아웃, localStorage로 아이디 저장 가능
  • 마이페이지: 회원의 주문내역, 리뷰 미리보기, 리뷰내역 상세보기, 회원정보 수정

백엔드에 seedData를 작성해서 서버가 실행될때마다 db에 저장되도록 했다.
이외에도 더 구현하고 싶은 기능들이 정말 많았었는데, 시간이 부족해서 선택과 집중을 할수밖에 없었다.
메인 페이지의 동영상과 이미지, 상품정보들은 후그와 가나스윔 사이트에서 가져왔다.

✔️ 문제 해결 과정

컴포넌트 분리
문제상황까지는 아니었지만... 리액트를 처음 사용해보고 팀과제이다 보니까 컴포넌트 분리 기준에 대해 이야기를 많이 나누고 시작했다.
팀원분이 잘 정리되어있는 영상들을 공유해주셔서 모두 시청하고 같은 이해수준을 가질수 있어서 도움이 되었다.
공통으로 사용되는 컴포넌트들을 미리 정해서 다른 담당자들끼리 공유해서 사용했다.
특히, 기획때부터 페이지의 세부 기능들에대해 정말 많은 이야기들을 나눠서 본인 담당이 아닌 부분에 대해서도 잘이해하고 있던것도 도움이 되었다고 생각한다.

모델 관계 설정
관계 설정이 은근히 헷갈렸다.
관계의 주인이 foreign key를 갖는다를 계속 떠올리면서 설정했다.
예를들어 회원과 리뷰의 경우, 회원 한명이 여러 리뷰를 쓸수 있으므로 회원이 리뷰id를 외부키로 갖는다.
가장 이해하기 어려운 부분은 주문 - 주문상품 - 상품 관계였다.
주문과 상품은 다대다의 관계인데, 다대다는 데이터 설계상 어려움이 있으므로 주문상품 모델을 추가하여 주문과 주문상품, 주문상품과 상품을 다대일의 관계로 설정한다고 한다.
팀원분과 정말 많은 사례를 찾아보고 정리했다.

추후에는 팀원들과 함께 보기 편리하게 ERD cloud 까지 생성했다.
ERD Cloud🔗

seedData
초기에는 각자의 pc에 필요한 데이터들을 입력하면서 작업을 했는데, 데이터가 공유되지 않다보니 번거로워서, seedData를 추가해보았다.

//seedData.js

const {
  User,
  Review,
  Order,
  Product,
  Cart,
  OrderItem,
  Category,
  Discount,
  syncAll,
} = require(`./models`);

const seedData = async () => {
  try {
    await syncAll({ force: true });
    
    const categories = await Category.bulkCreate([
      { name: `woman`, parent_id: null },
      ...,
    ]);
    ...
    console.log(`더미 데이터 생성 완료!`);
  } catch (error) {
    console.error(`더미 데이터 생성 중 오류 발생:`, error);
  }
};

module.exports = seedData;

seedData.js 폴더에 필요한 데이터들을 작성하고 app.js에서 실행하는 코드를 추가했다.

//app.js

const seedData = require("./seedData");
const startServer = async () => {
	...
    await db.init();
    await models.syncAll({ force: true }); 
    // force: true 옵션을 추가 -> db가 실행될때마다 기존 테이블 삭제 후 새로 생성
    await seedData();
    ...
};  

그런데 이렇게 했을 때 자꾸 오류가 났는데, 그 이유는 모델들간의 관계설정 때문에 삭제될때와 생성될때의 순서가 다르기 때문이었다.
챗gpt한테 관계설정한 것을 보여주고 순서 정리해달라고해서 수정했다.

//models/index.js

const syncAll = async () => {
try {
  // Drop tables in reverse order of dependencies
  await Review.drop({ force: true })
  await OrderItem.drop({ force: true })
  await Cart.drop({ force: true })
  await Order.drop({ force: true })
  await Product.drop({ force: true })
  await Category.drop({ force: true })
  await Discount.drop({ force: true })
  await User.drop({ force: true })

  // Recreate tables in order of dependencies
  await User.sync({ force: true })
  await Category.sync({ force: true })
  await Discount.sync({ force: true })
  await Product.sync({ force: true })
  await Order.sync({ force: true })
  await Cart.sync({ force: true })
  await OrderItem.sync({ force: true })
  await Review.sync({ force: true })

  console.log('All tables synchronized successfully')
} catch (error) {
  console.error('Error synchronizing tables:', error)
  throw error
}
};

순서를 정리하고나니 정상적으로 seedData가 db에 저장되었다.

aws ec2, s3
우리팀은 하나의 레포지토리에 백엔드와 프론트엔드의 프로젝트가 함께 있었고, ec2로도 각 서버를 실행할 수 있을 줄 알았다. 결론적으로는 불가능했다.
다른 오류도 있었을 수 있지만 일단 ec2가 너무 느려서 엄청 버벅댔기 때문에 뭘 수정하려고해도 먹통이 되어서 ec2를 삭제하고 다시 생성하는 걸 몇번 반복했다.
시간은 없고 ec2에서 두 서버를 돌리는 게 가능한건지 자체도 확신이 없어서 강사님께 질문을 드렸고, 강사님께서는 프론트서버를 s3로 배포하라고 말씀해주셨다.
따라서 ec2에서는 Mysql 설치, 레포지토리 클론, 백엔드 실행(백엔드를 계속 커두기 위해서 추후에는 npm run start가 아닌 pm2 start npm --name "backend" --run start로 실행했다)
s3로 로컬에서 생성한 .dist파일 업로드, 권한 및 엑세스 설정을 통해 배포에 성공했다.

📑 그 외 배운것들

classnames: 조건부 스타일링

className={`h-full w-1/2 ${tab === "review" ? "border-black" : ""}`}
className={cn('h-full w-1/2', {'border-black':tab})}

Link/Navigate/useNavigate

Link : 사용자가 클릭해서 페이지를 이동할 때
Navigate: 특정 경로에서 렌더링 시점에 이동시키고 싶을때(리다이렉트)
useNavigate 훅: 페이지 이동시 추가 로직이 필요한 경우, 특정 코드 실행이후 페이지 이동(결제하기 버튼 클릭 -> 결제 완료이후 -> 페이지 이동)

react-hook-form/zod
회원정보수정 기능을 구현할 때 사용해보았는데, 처음에는 기능이 너무 많아서 조금 막막하기도 했는데 하나씩 뜯어보면서 기능을 구현해볼 수 있었다. 유용한 기능들이 많아서 더 공부해보고 싶다!

axios import
services/index.ts에 base url을 정의해두어서 api 호출을 할 때 전체 url을 입력하지 않아도 된다. 그런데 나는 왜인지 전체 url을 입력하지 않으면 오류가 났다. 다른 팀원이 작성한 코드랑 비교해보니 axios를 import 할때 우리가 정의해둔 services/index.ts가 아닌 axios를 import해서 생긴 문제였다. import할 때 자동 완성되는 것을 선택해왔는데 앞으로는 더 주의해야겠다.

✔️ 결과

대상 🎉🎉🎉

상을 수상한 것도 기뻤지만, 팀원들과 각자 작업한 코드들을 합쳐서 하나의 서비스가 완성되어갈 때 재미있었고, 특히 배포까지 성공했을 때 굉장히 뿌듯했다.

✔️ KTP 회고 및 소감

💪 KEEP

  • 적고 적고 또 적고. 매일 회의를 할 때마다 Figma에 날짜별로 회의 내용들을 적었다. 회의 시작 전에 해야할 일들이나 얘기나눠야할 것들을 미리 적어두고, 회의 중이나 회의가 끝나고 정해진 내용들을 정리했다. 매일매일 진행상황을 확인하기 좋았고, 할일들을 정리하는데 도움이 되었다. wiki에 회의록을 작성하는 담당은 다른 팀원이 해주었는데 날짜별로 내용이 적혀있으니 회의록 정리할 때도 편리했다고 해주셨다.
  • conflict 함께 해결하기. 기존에 나는 conflict이 나와도 그냥 각자 해결하고, 문제가 생기면 다시 코드를 쓰면 되는거 아닌가 하는 생각을 가지고 있었는데(😂), 이번 팀에서는 머지할 때 함께 하고 pull을 받자고해서 각자 올려둔 pr들을 회고가 끝나면 머지하고 conflict이 발생하면 함께 해결했다. conflict을 함께 해결하니 빠르게 해결되는 것을 느꼈다!
  • Live share extention 사용. 여러명이 한명의 vscode에서 함께 작업할 수 있는 extention 이다. url을 통해 쉽게 접속할 수 있고, 각자의 위치도 보여서 특정인을 따라다닐 수도 있고, 실시간으로 작성되는 코드를 확인할 수 있다. 이번에 처음 사용해봤는데 재미있고 유용했다. 그리고 커밋을 남길 때 자동으로 co-authored를 작성해주어서 공통커밋을 남기는 데에도 편리했다.(공통 커밋을 남길 때는 터미널이 아닌 source control에서 해야 적용됨)

⛔️ PROBLEM

  • 예외처리나 오류 핸들링이 부족했다. 입력값이나 상태 검증, api 호출/응답시 예외처리를 많이 해주어야했는데 내가 작성한 코드들에서도 일관성이 없었고, 팀 전체적으로도 부족했다고 생각한다. 그때그때 필요한대로 코드를 작성하다보니 그런 것 같다. 다음에는 체계적으로 하고싶다..
  • 백엔드에서 관심사 분리를 제대로 하지 못했다. 우리는 route 폴더 안에서 api 응답과 기능적인 코드도 한번에 작성을 했는데, 마지막 피드백시간에 강사님이 지적해주셨다. 로직이 분리되어 있지않아서 유지보수와 확장성에 어려움이 있을 것 같다. Anemic Domain Model, Transaction Script, Domain Model Pattern 등에 대해 공부해야겠다.
  • 팀원들의 담당을 나누는 게 어려웠다. 어느 기능이 어려울지, 쉬울지 또 시간이 얼마나 걸릴지 등을 판단하기 어려웠고, 팀원들마다 속도나 능력치가 다르다보니까 적절히 나누는 게 어려운 것 같다. 다행히 팀원분들이 모두 정말 열심히 해주셨고, 본인 담당이 끝나면 서로 도와줘서 잘 마칠 수 있었던 것 같다. 앞으로 경험이 좀 쌓이면 이런 감도 더 생기면 좋겠다.

🔧 TRY

  • db를 각자 설치하는 게 아닌 docker 등을 사용해서 하나의 docker 파일을 가지고 공유하는 방법을 강사님이 말씀해주셨다. 실제 db를 가지고 활용하는 게 처음이라서 생각하지 못했던 부분이었고, 추후에서야 seedData를 입력했는데, 이 데이터도 계속 삭제되고 새로 생성되는 데이터들이라서 효율적이진 않은 것 같다. 다음에는 하나의 db를 공유해서 활용해보고 싶다.
  • 프로젝트를 마무리할 때 다같이 사이트를 보면서 디자인 통일이 안된부분, 고쳐할 부분을 함께 검토했다. 그런데 발표날 강사님께서 세세한 오류를 다 잡아내는 걸 보면서 테스트도 더 세세하게 해야함을 느꼈다.

💬 소감

정말 열심히 했고, 재미있었던 프로젝트였다. 크리스마스에도 회의하고, 새벽까지 하는 날도 많았고, 토의도 정말 많이했다. 배포까지 된 사이트를 보니 뿌듯함도 많이 느꼈고, 더 성장해서 더 좋은 서비스를 만들고 싶다는 생각도 들었다. 또, 공부할 것도 아직 한참 많겠구나라는 생각도... 🫠

크리스마스 이브에 9시까지 개발하고 크리스마스에도 만난 우리팀 🫶

0개의 댓글