taetaeo / tk-shopping-mall

Firebase + Express + NextJS + Graphql, + Node.js 쇼핑몰 프로젝트
1 stars 0 forks source link

:shirt: 온라인 의류 쇼핑몰 프로젝트

📌 Summary

온라인 의류 쇼핑몰 웹사이트입니다. 평소 이커머스와 프론트엔드에 관심이 많았고, 저와 같은 관심사를 가진 사람들에게 도움이 되었으면 하는 마음으로 개발하였습니다.

혼자서 구현했기에, 부족한 Back-End를 Firebase 서비스를 통해서 프로토타입으로서 보완하였습니다. Firebase를 처음 사용하면서, Storeage, Firebase Auth 등의 개념을 깊게 다질수 있었고 NoSQL를 실제로 사용하면서 개발 초기에 빠르게 FE만으로 프로토타입을 만드는게 더욱 의미가 있었습니다.

최근에 RestApi에서 GraphQL을 사용이 점점 늘어나면서, 처음으로 사용해보며 REST API를 하는것과는 다르게, URL을 통해 요청하는 방식이 아닌, 하나의 엔드포인트에 요청하는 쿼리에 따라 다른 응답을 받으면서 원하는 응답값만 받을 수 있다는 장점을 알게 되었습니다. HTTP 요청 횟수를 줄이고, 응답사이즈를 줄이면서 보다 유용성을 느낄 수 있었습니다.

* 주요 기능


:mountain: Background

원래 사이드 프로젝트로 BE 2명 / FE 1명으로 구성한 쇼핑몰 프로젝트를 시행했습니다. 협업 과정에서 BE의 작업 속도에 따라서 데이터를 받아야하는 FE입장에서는 진행함에 있어서 수동적으로 request에만 의존해야 했던 문제를 발견하였습니다. 이를 통해, 단순 FE단에서 먼저 구현해보고 BE와 나중에 추가적으로 병합할 수 있으면 작업 속도와 효율성이 좋을 것이라 판단하였습니다. 그렇게 FE단에서도 BE의 흉내를 낼 수 있는 Firebase를 사용해보고 프로젝트를 만들어낼 때, 프로토타입으로 적용하기에 큰 이점이 될 수 있다는 것을 알게 되었습니다.

쇼핑몰의 컨셉으로는 평소 www.29cm.com 라는 의류쇼핑몰을 즐겨 찾아봅니다. 심플하면서도 감각적이고 모던한 분위기를 느끼게 하여 매력적이라 생각하였습니다. 큰 기능이라 할 수 없지만, 유저마다 상품 추가, 장바구니 등을 구현할 수 있다면 기본적인 BE에 대한 이해도 될 수 있다고 생각하여 이 프로젝트를 구상하였습니다. 이것이 바로, 이 프로젝트를 개발하게 된 배경입니다.


🔍 What I Learned

프론트엔드만 프로젝트를 수행하며 서비스를 구현해보기에는 백엔드에 대한 공부가 부담이었고, 이번에 Firebase를 공부하면서, 프론트엔드 개발자에게는 정말 필요한 서비스겠다는 생각을 하였습니다.


:hammer_and_pick: 구현 결과

영상 보러가기

1. Home 페이지

2. 로그인

3. 장바구니 추가

4. 검색 페이지


:thinking: 개발 일지 및 회고

제목
1. React의 SSR 프레임워크인 Next.js 를 선택하게 된 이유 1) 블로그 바로가기
2. Next.js의 SSR 1) 블로그 바로가기
2) 이슈 바로가기
3. graphql & firebase 연동 1) 블로그 바로가기
4 Firebase 색인 1) 블로그 바로가기
5 Firebase Auth 1) 블로그 바로가기




:diamond_shape_with_a_dot_inside: 프로젝트 소개

개요 : 개인 프로젝트

주제 : 온라인 의류 쇼핑몰 프로젝트


1. 컨벤션 규칙

1.1. 커밋 컨벤션

feat: 파일, 폴더, 새로운 기능 추가
fix:  버그 수정
style:  코드 스타일 변경
docs: 문서 생성, 추가, 수정(README.md)
refactor: 코드 리팩토링
chore: 코드 수정 (JSON 데이터 포맷 변경 / scss 변경 등)

1.2. 브랜치 컨벤션

신규: new-something-you-made
수정: fix-something-you-fixed
개선: improve-something-you-made-better

1.3. 폴더 구조 및 파일명 규칙

1) client

base : 프로젝트에서 제공하는 기본이 되는 UI를 담당.
common : 프로젝트의 바탕이 되는 공통으로 사용하는 컴포넌트를 담당.
layouts : 프로젝트에서 공통으로 사용하는 레이아웃을 담당.
sections : 페이지를 구성하는 컨텐츠단위 컴포넌트를 담당.(페이지에서는 단순 라우팅만 역할하기 위함)
hooks : 공통으로 사용하는 hook을 담당.
pages : 사이트의 페이지 라우팅을 담당.
graphql : graphql 스키마 담당
service : query관련 라이브러리 (react-query/graphql-request)
recoil : 전역상태 관리를 위한 폴더 (recoil-atom/selector)
style : 전역으로 사용하는 GlobalStyles와 theme를 담당
types : 프로젝트의 전반적인 타입들을 담당.
utils : 프로젝트에서 사용하는 상수(constants)나 필요한 함수(helpers)를 담당.

2) server

schema : graphql typeDefs를 위한 스키마
resolvers : graphql resolver 담당


2. 프로젝트 소개

2.1. 프로젝트 WBS

2.2. 프로젝트 설계

2.3. 프로젝트 요약

2.3.1. 사용 기술

2.3.2. 프로젝트 흐름도

2.3.3. 페이지 구성

홈 : '/'
마이페이지 : '/mypage',
로그인페이지 : '/signin',
회원가입페이지 : '/signup',
남자 상품 전체 페이지 : 'shop/category?list=men&category_code=m_all'
여자 상품 전체 페이지 : 'shop/category?list=women&category_code=w_all'
장바구니 페이지 : '/cart',
주문조회 페이지 : '/mypage/orders',
좋아요 페이지 :'/mypage/likes',
이벤트 페이지 : '/event'
상세 페이지 : '/detail/:id'
검색 페이지 : '/search'
검색 결과 페이지 : '/search/keyword'
1:1 문의 페이지 : '/qna/

2.4 데이터 스키마

2.4.1. server

1) Product Schema
  type Category {
    category_lg: String!
    category_md: String!
    category_sm: String!
  }
  type Product {
    id: ID!
    brand: String!
    name: String!
    image_url: String!
    origin_price: Int!
    discount: Int!
    category: Category!
    createdAt: Float!
  }

카테고리

  1. category_lg : men / women 대분류

  2. category_md : top / bottom / outer 등 중분류

  3. category_sm : long / short / hoody 등 소분류

2) cart Schema
  type CartItem {
    id: ID!
    amount: Int!
    uid: String!
    createdAt: Float!
    product: Product!
  }
  1. uid : firebase Authentication에서 제공하는 고유의 uid
  2. product : 상품 스키마의 타입

3) search Schema

  type Search {
    id: ID!
    product: Product!
  }

  extend type Query {
    searchItems(keyword: String!, cursor: ID): [Product!]
    searchBrand(keyword: String!): [String]
  }
  1. searchItems : 검색 keyword를 기준으로 product를 내보내주도록 구현
  2. searchBrand : 검색 키워드 변경시에, 추천 브랜드를 나타내주기 위한, 추천 Brand가 보여지도록 구현

4) Event Schema

  type Event {
    id: ID!
    image_main: String
    image_lg: String
    image_md: String
    image_thumb: String
    createdAt: Float!
  }

  extend type Query {
    events: [Event!]
    event(id: ID!): Event!
  }
  1. image_main : / 경로의 슬라이드에 들어갈 이미지 URL
  2. image_lg : / 경로에 들어갈 Event 데이터
  3. image_thumb : /event 페이지에 들어갈 썸네일 이미지 URL
  4. image_lg : /evnet:id 페이지에 들어갈 이미지 URL


2.4.2. client

1) Product Schema
query GET_PRODUCTS {
    products {
      id
      brand
      name
      image_url
      origin_price
      discount
      createdAt
      category {
        category_lg
        category_md
        category_sm
      }
    }
  }
  query GET_PRODUCT($id: ID!) {
    product(id: $id) {
      id
      brand
      name
      image_url
      origin_price
      discount
      createdAt
      category {
        category_lg
        category_md
        category_sm
      }
    }
  }
  query GET_SELECTED_PRODUCT(
    $category_lg: String!
    $category_md: String
    $category_sm: String
    $cursor: ID
  ) {
    selectedProducts(
      category_lg: $category_lg
      category_md: $category_md
      category_sm: $category_sm
      cursor: $cursor
    ) {
      id
      brand
      name
      image_url
      origin_price
      discount
      createdAt
      category {
        category_lg
        category_md
        category_sm
      }
    }
  }
 mutation ADD_PRODUCT(
    $brand: String!
    $name: String!
    $image_url: String!
    $origin_price: Int!
    $discount: Int!
    $category_lg: String!
    $category_md: String!
    $category_sm: String!
  ) {
    addProduct(
      brand: $brand
      name: $name
      image_url: $image_url
      origin_price: $origin_price
      discount: $discount
      category_lg: $category_lg
      category_md: $category_md
      category_sm: $category_sm
    ) {
      brand
      name
      image_url
      origin_price
      discount
      category_lg
      category_md
      category_sm
    }
  }
2) Cart Schema
  mutation ADD_CART($id: ID!, $count: Int, $uid: String!) {
    addCart(productId: $id, count: $count, uid: $uid) {
      id
      amount
      uid
      createdAt
      product {
        id
        brand
        name
        image_url
        origin_price
        discount
        createdAt
        category {
          category_lg
          category_md
          category_sm
        }
      }
    }
  }
3) Search Schema
  query GET_SEARCH_ITEMS($keyword: String!, $cursor: ID) {
    searchItems(keyword: $keyword, cursor: $cursor) {
      id
      brand
      name
      image_url
      origin_price
      discount
      createdAt
      category {
        category_lg
        category_md
        category_sm
      }
    }
  }


3. 개발 하이라이트


4. 실행 방법

4.1. 설치

npm i 또는 npm install
yarn

4.2. 실행

# 1. client
cd client
yarn
yarn run dev

# 2. server
cd server
yarn
yarn run dev