회고

React와 Node.js + MongoDB로 쇼핑몰을 만들어보며...

hamsoter 2022. 5. 19. 20:35

이번엔 React와 Node.js를 사용하여 쇼핑몰을 만들었다. 약 2주에 걸친 개발 기간 동안 느낀 점을 기록하기 위해 회고글을 남긴다. 

 

프로젝트 소개: 모퉁이 꿈 다락방
(https://corner-dream-atelier.herokuapp.com/)

랜딩 페이지 이미지

달러구트 꿈 백화점이라는 책에서 영감을 받아 만든 꿈을 팔고 살 수 있는 쇼핑몰이다.
'통신판매에 도전하는 요정들의 스타트업'이라는 지존 오타쿠 같은 컨셉을 잡고 만들었다 으하하. 
 
간단히 아래와 같은 기능들이 있다. 
 
1. 상품 조회
2. 상품 구매
3. 상품 생성
4. 카트에서 삭제
5. 카트에서 결제
6. 구매한 상품정보 조회
 
강의에 나온 기능에서 +@로 개선할 부분은 개선하고, 추가할 부분은 추가하는 식으로 진행하며 나만의 프로젝트로 점점 바꾸어나갔다. 
 

사용한 기술 및 서비스

React (FE)
  - React Router Dom
  - Ant Design (UI)
  - React Cookie
  - Redux
  - multer s3
- Node.js (BE)
- MongoDB (BE)
- AWS s3 (Service 이미지 호스팅)
- Heroku (Service 배포)
- paypal (Service 결제)
 
크게는 React, Node.js 이렇게 두 가지로 개발했다.
DB는 MongoDB를 사용했다.
 

페이지별 기능

랜딩페이지 (main)

랜딩 페이지 이미지

해당 페이지는 MongoDB에 접속하여 DB에 저장된 상품 데이터를 불러오는 로직이 주를 이루었다.
상품의 장르와 가격을 이용하여 알맞게 걸러진 상품만 보여줄 수도 있다.
상품 숫자가 12개를 넘을 시 '더 가져와!!' 버튼이 생긴다. 누를 시 상품을 최대 12개 더 가져온다.
 
쿠키를 이용하여 팝업을 띄운다. 사이트에 접속할시 아래와 같은 팝업이 뜬다.
 

랜딩페이지 팝업

오늘 하루 보지 않기를 체크하고 팝업을 닫을 시 24시간 동안 활성화되는 쿠키를 저장한다. 매번 접속할 때마다 쿠키가 있는지 검사하여 팝업을 띄운다.
 

디테일페이지

상품을 클릭할 시 오게 되는 디테일 페이지이다.
상품의 uid를 url로 사용했다. 그리고선 url에서 뜯어온 uid를 이용하여 mongoDB에서 상품의 데이터를 찾아온 후 뿌려준다.
꿈 바구니에 담기 버튼을 누를 시 유저의 카트에 상품이 담긴다.
 

상품 등록 페이지

로그인한 유저가 상품을 올릴 수 있는 페이지이다.

유저에게 받은 input들을 mongoDB에 저장해준다. 이 부분은 크게 어렵지 않았으나... 막상 이미지 업로드 부분에서 애를 먹었다. multer를 잘 쓰다가... 막상 배포 시에 이미지 업로드가 되지 않는 문제를 발견. 프론트단에서 자꾸 404로 빠꾸를 먹었다. 보아하니 원래 heroku에서는 파일을 올려도 30분 뒤면 사라지기 때문에 무료 버전에서는 파일을 저장하지 않는 것을 권장한다고 한다. 사실 이 때문에 올라가지 않은 건 아닌 것 같지만... 그래도 일단 권장하지 않는다고 하니 일단 이미지를 호스팅 할 수 있는 다른 방법을 찾아봤다. aws s3라는 저장소를 이용하여 호스팅 하는 경우가 흔한 듯하다. 일단 박치기로 도전했지만 시간을 꽤나 많이 잡아먹었다. 그 과정에서 겪은 일들을 간단하게 포스팅하기도 했다. 
 

꿈 바구니 페이지(cart)

일단 기능은 장바구니의 기능을 충실하게 수행한다. 선택한 상품을 paypal로 결제할 수 있다. 
결제가 완료된 뒤 user의 history에 완료된 주문을 저장한다.
 
개인적으로 힘들었던 페이지이다. 기존 강의에서는 장바구니에 select 기능이 없었고 해당 페이지에서 수량을 바꿀 수도 없었다. 결제한 후 한 번에 카트 내용을 다 비워버리는 식이었다. 그 방식보단 선택된 상품만 결제하는 걸 해보고 싶었는데 막상 이 간단한 기능을 넣기 위해서 바꿔줘야 할 게 많았다. 
 
결제를 할 때 업데이트해줘야 할 카트 관련 객체만 해도 두 개였다.
  1. user객체마다 가지고 있는 심플한 cart 객체... 카트에 담긴 개수와 uid 같은 간단한 정보만 담겨 있다.
  2. 상품의 디테일한 정보(이름, 설명, 판매자...)까지 담고 있는 cartDetail객체
 
그리고 무엇보다 카트에서 상품이 지워지고 수량이 변경될 때마다 결제할 합계를 나타내 주는 totalPrice의 계산이 실시간으로 일어나야 한다. (중요)
1. 상품이 지워질 때
2. 수량이 변경될 때
3. 결제가 완료될 때
 
이 모든 과정을 끙끙대며 처리하긴 했지만... 기존 코드의 틀을 최대한 해치지 않고 기능을 붙이려 하다 보니 코드가 상당히 지저분해졌다. 😥
 
+
 

다른 얘기지만... 결제에 대한 부분은 고민을 많이 했는데, 왜냐면 달러구트 꿈 백화점에서는 꿈 값을 현금으로 지불하지 않기 때문이다. 현금이 아니라 고객들이 꿈을 꾸며 느낀 감정으로 꿈값을 지불한다. 정말. 정말... 정말 많은 고민을 했다... 결제 기능을 넣을까 말까... 하지만 내가 지금 취업 준비를 하는 마당에... 이런 고민을 하는 게 맞는가. 하고 페이팔 기능을 넣었다. 감성이 파괴된 거 같아서 약간 슬프지만...

 

주문 내역 페이지

결제 완료 시 모달이 하나 뜨고 user히스토리를 보여준다. (제일 간단)

느낀 점

 

이 DB가 신기하다🙄

mongoDB에는 편리하고 다양한 문법들이 정말 많이 있었다. 이런 것까지? 하는 것도 전부 있었다... firebase를 사용할 때도 그랬지만 mongoDB 역시나 메서드를 이용한 쿼리 작성법이 신기했다.
 
다음은 랜딩페이지에서 '더보기' 버튼을 눌러서 상품을 12개 더 가져오게 될 때 서버에서 동작하는 mongoDB의 쿼리이다. 중첩이 많이 나온 게 신기해서 따로 메모해두었다.

Product.find(findArgs)
      .find({ $text: { $search: term } })
      // uid값으로 User를 찾고 writer에 User 객체를 담음
      .populate("writer")
      // 기존에 불러온 데이터들은 skip
      .skip(skip)
      // limit만큼 건너뛰고
      .limit(limit)
      .exec((err, products) => {
        if (err) return res.status(400).json({ success: false, err });

        // 조건에 걸맞는 데이터만 불러온다
        return res
          .status(200)
          .json({ success: true, products, postSize: products.length });
      });

 
 

눈이 떠진다는 경험

해당 프로젝트를 시작하기 직전 나는 React + Firebase 기반으로 일기를 쓰는 사이트를 만든 경험이 있다. 완성 후 거의 바로 직후 후련하다!라는 감정보다는 “나는 작동하는 것을 만들었지만, 과연 내 방식이 맞는지 모르겠어”라는 의문이 생겼고... 다른 사람이 볼 때 얼마나 부끄러운 코드를 짰는가에 대한 불안으로 잠도 잘 못 이룰 지경이었다. 그런 불안을 가지고 john ahn님의 따라 하며 배우는 노드 리액트 쇼핑몰 강의를 듣기 시작했는데, 아주 만족스러운 아웃풋을 얻을 수 있었다. 
 
쇼핑몰이라는 여러 기능이 묶인 프로젝트를 진행하는 강의이다 보니 프로젝트 구조를 깔끔하게 나누는 게 얼마나 중요한지에 대해 깨달을 수 있었다. 아 이런 식으로 파일을 분리하면 훨씬 편하게 볼 수 있구나... 하는 감이 확 와닿았다. 나의 이전 일기 쓰기 프로젝트는 실은 구조랄 게 없이 컴포넌트들이 뒤죽박죽 섞여 있어서 개발하는데 많이 힘들었지만, 이번 프로젝트의 폴더의 구성은 정말 깔끔하게 기능별, 서버, 프론트, 설정 파일 등이 전부 명확하게 나뉘어 있어 파일을 열어보지 않아도 어떤 기능이 어디에 있는지 딱 알 수 있게끔 되어 있었기에 개발하는 내내 매우 편했다.
 
메서드를 어느 컴포넌트에 구현할지에 대해서도 더 고민할 필요가 있다는 것을 깨달았다. 버튼 클릭 이벤트라고 단순히 버튼이 있는 컴포넌트에 기능 메서드를 구현하는 것이 아니라 제 역할에 어울리는 컴포넌트가 있다면 그곳에 구현하는 것이 나중에 찾아보기 훨씬 편하다는 것을 느꼈다.
 
공식 문서를 보며 박치기 식으로 공부하는 것도 나름의 장점이 있었지만, 강의를 보는 것에도 이런 장점도 있구나. 역시 '답지가 있다'는 것은 이 답지를 어떻게 쓰느냐에 따라서 독이 되기도 약이 되기도 하는 것 같다.
앞으로의 일을 그리기 위한 참고서가 된다면 약이겠지만 그냥 당장의 포트폴리오를 완성하기 위한 해답지일 뿐이라면... 발전을 막아서는 독이라고 생각한다. 나는 잘 달여서 약으로 먹어야지.🤣 (과연...)
 

Redux 첫 사용!

Redux에 대해선 아무것도 모른 채로 강의를 듣게 되었는데, 상태를 전역으로 관리한다는 것이 얼마나 편리한 일인지 알 수 있었다. 바로 이전 프로젝트에서는 구글 로그인 인증 정보를 부모 state가 가지고 있고 그걸 계속 자식 컴포넌트의 props로 내려주는 식이었다. (끝없는 폭포처럼 내려가던 props...) 전역에서 관리하는 state가 있고 없고의 차이는 생각보다 컸다! 이 좋은 걸 왜 이제야 알았을까... 이제부터 애용해주마.
 
 
아무튼 얻어가는 게 많은 프로젝트였다. 이다음 프로젝트를 진행할 때 어떤 식으로 갈피를 잡아야 할지, 좋은 길잡이가 되어줄 것 같다. 
 


좋아하는 부분들

또 돌아온 좋아하는 뿌듯함의 시간.
이 아래론 안 읽어도 좋습니다!
 
 
이번에도 역시나 사이트의 디자인과 일러스트에 조금 신경 썼다! 이렇게 보여지는 부분을 좋아하는 걸 보면 정말 프론트가 적성에 맞는가 싶다가도... DB에 정상적으로 데이터가 들어갈 때 나도 모르게 으악!! 소리 지른 걸 보면 백도 좋아하는 건 분명하다...ㅋㅋㅋ

파비콘

 

밤하늘을 그린 파비콘
파비콘 적용 이미지

이번에도 역시나 파비콘을 직접 그렸다. 도트 찍는 거 왜 이렇게 재밌는 걸까...ㅋㅋㅋㅋ 파비콘은 정말 조그맣지만 찍고 나서 보면 정말 뿌듯하다.

벡터 일러스트들

벡터로 그린 배너와 팝업 디자인 (떨고 있는 유령과 경찰 달팽이)

아무래도 캐러셀 배너가 있어야 좀 쇼핑몰 느낌이 나지 않겠어? 하고 넣어보았는데 역시 1,2,3,4 숫자만 적힌 캐러셀은 별로였다. 그래서 코딩하다가 기력이 쏙 빠질 때면 Figma를 켜서 벡터로 그림을 그렸다.
예전에 어도비 일러스트로도 벡터 일러스트 그리는 걸 좋아했는데 돈이 없어진 이후 어도비를 구독하지 못한 이후로는 못 그린 지 한참이다. 이번에 Figma에서 오랜만에 그려보았는데 재밌구나. 와중에 유령쨩은 또 등장했다. 👻
 
이번엔 동적인 배너를 만들어보고 싶어서 css 애니메이션도 넣었다. 쏘 귀염둥이...
 
 
 
귀여워요
취업하려면 쇼핑몰 정도는 만들어봐야 하지 않을까? 그러려면 이번엔 상업적인... '팔리는 뭔가'를 만들어야 해... 하는 불안에서 시작한 쇼핑몰 프로젝트이지만... 결국 또 귀여운 걸 만들어버렸다.
 
"그냥 쇼핑몰은 재미가 없잖아!" 하는 마음에서
"기능만 쇼핑몰이고 아이템은 내맘대로면 아무거나 팔아도 되는 게 아닌가?" 하고는...
작년에 재밌게 읽은 책(달러구트 꿈 백화점)이 문득 떠올라서, 그곳의 세계관을 오마주한 사이트를 만들어보기까지!
헤헤 아주 얼렁뚱땅 흘러가는 게 정말 내가 만든 사이트 같다.
 
최근 진행한 프로젝트들이 작은 관심을 받게 된 후 내 특유의 감성이 마음에 쏙 든다는 칭찬을 (너무 감사하게도...) 종종 듣게 되었는데. 이번 사이트 역시나 아마 그런 감성을 좋아하는 분들이라면 마음에 들어 하는 분위기가 아닐까? 싶다 헤헷

별 거 아닌 TMI

「견디어라」는 나의 지인이 만든 필명입니다...

유명 꿈 제작자 '견디어라'의 신작 출시 기념을 알리는 배너의 메세지와 그것을 직접 지어주는 카카오톡 메세지

작은 이스터에그들!

귀여운 이스터에그를 숨겨두었다. 사실 숨기려고 한 건 아닌데 그냥 만들다 보니 귀여워서... 그런데 아무도 안 알아주면 눈물이 고일 것만 같아서 굳이 써본다.
 
사이트에 들어가서 직접 찾아보고 싶다면 먼저 찾아보고 읽어보세요.
 

더보기

1. 바닥을 잘 보세요

푸터를 발견한 힝님

홈페이지 푸터에 있는 오시는 길. 헤헤

제발 찾아줬으면 하는 염원을 담아 쓴 부분이었는데!! 너무 귀엽지 않은가...


2. 근데 여기 누가 숨어 있는 거 같은데요?

주문 완료 후 뜨는 모달을 드래그해보세요

갑자기 분위기 메롱


3. 동산에서 푸딩 점프!

푸딩처럼 점프하는 배너의 토끼 이미지

css만으로도 이렇게 귀여운 기분이 될 수 있다니 최고다...

 


UI 컴포넌트를 다루는 데에도 전보다 훨씬 익숙해져서 재밌게 개발했다. aws까지 이용할 생각은 없었는데... 귀하고 쓴... 경험이었다. 생각보다 얻어가는 게 많은 시간이었다.
 
나는 전부터 완전히 보여주는 프론트 영역에 시간을 많이 쓰는 자신에 대해 비판했었다. UI UX에 대해 아는 것도 없으면서, 쓸데없는 기능을 넣는 데에 자꾸만 시간을 쓴다고... 이럴 시간에 더 멋진 기능을 보여주는 게 좋지 않을까. 여기서 alert를 모달 창으로 바꾼다고 뭐가 달라지는데! 좀 더 알고리즘 어쩌구를 해야 하지 않냐! 하며 스스로를 꾸짖었다.
하지만... 그래도 난 즐거운 것을 만드는 게 좋은 것 같다. 그것이 멋진 기능이든 디자인이든 뭐든지 내가 즐거운 것이라면 무엇이든 만들며 행복하다! 그리고 이 몽글몽글하게 눌러 담은 마음이 많은 사람들에게 가서 닿기를 원한다.
 
나는 하루에 반 발자국씩 깽깽이 발로 걸어서 돌이켜보면 '아 재밌게 걸어오다 보니 벌써 여기까지...' 하는 그런 회상을 하는 할머니가 되고 싶다. 개발 뿐만 아니라 모든 일에 있어서!
 
이런 걸 생각하면 역시 나는 엄청난 로직을 짜는 개발자가 될 수는 없을지도 모른다. 하지만 누군가에겐 "여기 내가 정말 좋아하는 사이트!"라는 말을 듣는... 그런 사랑받는 공간을 만드는 개발자가 될 수 있지 않을까? 엄청난 개발 실력을 가진 사람은 멋지지만... 분명 나에게도 그만큼 반짝이는 무언가가 있다고 생각한다. 말로는 잘 설명 못할 추상적인 부분이지만... 나는 그걸 놓치지 않고 잘 갈고닦고 싶다. 채용시장아 이런 날 알아봐 줘... 
 

아이돌마스터 샤이니컬러즈 해당 대사가 나오는 플레이 화면

ㅎㅎ...
 

아이돌마스터 샤이니컬러즈 해당 대사가 나오는 플레이 화면2

> _ <