Project

웹사이트 미니 프로젝트를 하고 나서...(feat.SIMPLE)

DigIT_JHB 2023. 1. 15. 22:04

SIMPLE

SIMPLE WEBSITE

1. 미니 웹사이트 프로젝트

 2023.01.02~2023.1.13까지 진행된 웹사이트 제작 프로젝트. 

4명의 프론트엔드와 2명의 백엔드 인원이 모여서 작게나마 의미 있는 프로젝트를 만들려고 모두들 열심히 노력했다.

나는 백엔드를 맡았고, 2주 간의 일정을 관리하는 Project Manager도 겸하게 되었다.

 

2. SIMPLE의 소개

 SIMPLE은 心(마음 심)과 PLACE를 합친 말로,

가심비를 채워주는 제품을 제공한다는 계획으로 만들어진 사이트다.

 

가심비는 비용과 상관없이 만족스러운 것을 구매하는 소비 행태로,

가심비를 추구하는 MZ세대를 주 타겟으로 삼았다. 

 

따라서 가심비를 채워줄 상품이 무엇이 있을까 고민하다가,

캠핑에 감성을 더해주고 그 공간을 가치있게 바꿔주는 캠핑 용품을 팔아보면 좋겠다는 생각을 하게 되었다. 

 

3.  진행 과정

효율적인 프로젝트 진행을 위해 Agile 방식을 채택하였고, 팀원 서로의 진행 상황을 알 수 있도록 Trello를 활용했다.

또한 새로운 아이디어나 의견을 들어보기 위해 매일 아침 Daily meeting도 진행했다.

 

백엔드는

1.초기환경세팅

2.DB모델링

3.REST endpoint 선정

4. 더미 데이터 작업

을 기본으로 하고

 

 로그인/회원가입/메인페이지/카테고리별 상품리스트/상품 상세페이지/검색/장바구니/결제 API를 제작하게 되었다.

 

4. Project Manager로서

 팀원들의 일정을 관리하는 Project Manager로서 가장 크게 걱정했던 부분은 바로 '나' 자신이었다.

나의 신분 변화(????)로 인해 약 3일 정도를 프로젝트 기간 중 참여하지 못하기 때문에 다른 팀원한테 피해가 갈까 걱정이 많이 되었다. 또한 프로젝트 기간이 14일이 아니라 실제로는 많아야 12일 정도였기 때문에 더 신경을 쓸 수밖에 없었다. 

따라서 일정을 짤 때 가장 크게 염두에 둔 것은

2주가 아니라 1주일 내로 전체적인 것을 다 짜보는 것이었다. 

 

(사실 이 부분은 2주를 풀로 참여했어도 변함없었을 것이다.

개인적으로 목표는 최대한 크게 잡아서 타이트하게 진행하고

남은 기간을 마음 편히 또는 수정하고 완벽을 기하는 게 맞다고 생각하기 때문이다.

그리고 이 생각을 팀원들도 수긍해 줘서 참 감사하다.)

 

이를 위해 매일 미팅을 할 때마다 팀원들의 진행 사항을 항상 체크해야 했고,

힘든 점이나 요구사항 등을 매번 확인하여 시간 지체 없이 진행되도록 해야 했다.

한마디로 모든 게 유기적으로 프로젝트가 진행되게 했어야 했다.

 

(어쩌면 나만 그렇게 생각했을 수도 있다. 노력을 한다고 했으나 팀원들한테는 그렇게 보이지 않았을 수도 있으니......)

 

목표는 1주일이었지만

사실 내 개인적인 생각으로는 전체적인 작업이 그래도 대략 10일 정도면 끝날 것이라고 예상했다.

나는 일정 상 2023-01-09~2023-01-11을 거의 참여를 못하기 때문에

원래 내가 맡았던

로그인/회원가입/메인페이지/카테고리별 상품리스트/상품 상세페이지/검색은

2023-01-08일까지 끝내고 돌아갔다.

 

그리고 결론적으로는 마지막날 금요일 아침이 되어서야 끝났다.

백엔드는 수요일까지 마무리가 될 줄 알았으나 다 완료되지 못하여

내가 나머지 장바구니와 결제 관련 API까지

혹시나 하는 걱정에 만들어서 목요일 마무리할 수 있었다.

프론트쪽은 대부분 수요일까지 마무리되었지만 

상품 상세페이지에서 금요일 아침까지 계속 오류가 발생했다.

계획했던 것들은 다 원활하게 되었으면 하는 마음에

내가 가서 일일이 확인하면서 다행히 마무리할 수 있었다.

 

5. 세부 구현 내용

(사실 대부분 모든 것을 다 건드렸다......)

 

1. 회원가입

-http://(IP ADDR):(PORT)/signup (METHOD: POST)

이름/이메일/패스워드/전화번호를 필수로 입력한다. (body값으로 전송)

만약에 입력되지 않았으면

입력되지 않은 값이 무조건 입력되어야 한다고 error 메시지를 반환한다.

 

패스워드는 Bcrypt를 이용하여 암호화된 것으로 저장했다.

 

추가적으로,

입력된 이메일에 대하여

DB에 있는지 없는지 검사 후에 동일한 유저가 없을 때만 회원가입 가능하게 했다.

 

2. 로그인

-http://(IP ADDR):(PORT)/signin (METHOD: POST)

 

이메일/패스워드를 이용하여 로그인한다.

이메일이 없거나 패스워드가 맞지 않으면 다시 로그인하게 error 메시지를 반환한다.

 

로그인이 되면

user의 이름/ user의 보유 포인트/ user의 jwtToken/ user의 장바구니 개수를 

response로 보낸다.

 

3. 메인페이지 아이템리스트 불러오기+카테고리별 아이템 리스트 불러오기 + 검색 아이템 리스트 불러오기 (통합 API)

-메인페이지(신상) :  http://(IP ADDR):(PORT)/items?sort=new (METHOD: GET)

-메인페이지(가격 낮은 순): http://(IP ADDR):(PORT)/items?sort=cheap 

-카테고리별(0:전체보기/ 1:캠핑용품/ 2:조명 + 랜턴/ 3: 라이프스타일): http://(IP ADDR):(PORT)/items?category=

-상품상세페이지: http://(IP ADDR):(PORT)/items/:itemId

-검색 : http://(IP ADDR):(PORT)/items?search=

(기본적으로 아이템리스트는 신상 기준으로 정렬되어 있으며 높은 가격순, 낮은 가격순을 지원한다)

 

상품 Id, 상품 이름, 상품 썸네일 주소, 상품 가격, 상품 카테고리 이름, 상품 간략 설명, 상품 상세 설명, 브랜드 이름, 상품의 옵션 Id, 상품의 옵션 내용, 옵션의 카테고리(ex.color, size 등등), 옵션 카테고리 Id를

response로 보내게 된다.

 

처음에는 위에 있는 API를 각각 만들려고 했다.

상품 상세 페이지 API가 다른 팀원에 의해 먼저 만들어져 있는 상황에서

그때 사용한 DB Query문이 다른 페이지에도 동일하게 사용되어야 했다. (Query문을 내가 짜서 그런가......? 물론 조금씩 다르기는 하다)

상품과 관련된 옵션들도 프론트쪽으로 보내줘서 장바구니나 결제를 할 때 거의 동일하게 데이터를 받기 때문이다. 

그래서 DEFAULT QUERY를 만들고 모듈화 하여 QUERY문을 조금씩 수정함으로써 DB로부터 데이터를 받도록 하였다.

 

나중에 추가적으로 작동 가능하게

한 페이지 당 20개씩 상품을 보여주는 페이지네이션도 구현해 놓았다.

 

4. 장바구니 API

-장바구니 리스트 가져오기: http://(IP ADDR):(PORT)/carts (METHOD: GET)

-장바구니 추가: http://(IP ADDR):(PORT)/carts (METHOD: POST)(body:itemId,quantity,optionId)

-장바구니 수정: http://(IP ADDR):(PORT)/carts (METHOD: PATCH) (body: cartId,quantity)

-장바구니 삭제: http://(IP ADDR):(PORT)/carts/?cartId= (METHOD: DELETE

 

장바구니는 다른 팀원이 만들어 놓았는데, 

처음에 add할 때 itemId, quantity를 받고 그에 따른 optionId를 입력받아서 추가하는 것은 문제없다고 생각했다.

그런데 수정이나 삭제할 때도 itemId를 받게 되면 다른 옵션을 가지고 있는 동일한 아이템에 대하여 구분을 할 수 없다고 생각하여

팀원과 상의 하에 cartId를 입력받기로 변경하였다.

 

5. 결제 API

-결제: http://(IP ADDR):(PORT)/order (METHOD: POST) (body: cartId[],totalPrice,paymentMethod)

-주문 내역: http://(IP ADDR):(PORT)/order (METHOD: GET)

 

주문할 때는 결제할 것들의 cartId를 배열로 받는다.

고객의 Point는 잔고를 확인하게 되고,

고객의 order 기록을 남긴다.

order_items에다가 주문한 상품들을 기록하고

옵션이 있는 상품에 대해 order_item_options에다가 추가 기록하게 된다.

그리고 장바구니 리스트에서는 사라지게 된다.

 

6. 소감

 

1.  팀원들과의 소통은 정말 중요하다.

 2주동안 자기가 맡은 일을 완벽하게 해내기도 쉽지는 않다.

회의 또는 기획에서 서로가 이해를 하고 동의를 했더라도 완전하지 않을 수 있다.

프로젝트를 진행하면서 서로의 생각이 조금씩 틀어질 수도 있고 예상치 못한 갈등으로 이어질 수도 있다.

프론트쪽은 아무리 페이지 레이아웃을 잘 만들었다고 해도 백엔드와 통신하면서 다 갈아엎어야 하는 상황도 발생하고,

백엔드 쪽은 POSTMAN으로 아무리 잘 결과가 나와도 프론트와 연결하면서 자기가 몰랐던 에러와 빈틈을 마주해야 한다.

또한 어쩌면 인간관계에서 흠집이 날 수도 있다.

 

우리 팀은

다행히 인간관계에서는 문제가 없었던 것 같고

프론트끼리 또는 백엔드끼리 싸울 일도 없었던 것 같다. (다른 팀들에서는 너무 많았어서 걱정을 할 수밖에 없었다.)

프로젝트를 진행하면서 갈아엎을 일도 없었기에 어쩌면 생각보다 성공한(?) 것으로 보이지만

조금이라도 더 세심하게 소통을 했으면

훨씬 시간을 아끼고 좋은 결과를 낼 수 있지 않았을까 하는 생각을 한다.

 

(그리고 나만 그런지는 모르겠지만

항상 팀원들한테 감사한 마음을 갖고 프로젝트를 하는 게 좋다고 생각한다.)

 

2. 어쩌면 더 집중하고 더 노력해야 한다.

 이번에 진행하면서

내가 맡은 업무를 일주일 안에 끝냈지만

개인적으로는 5일 안에(금요일까지) 끝낼 생각이었다.

로그인과 회원가입을 1일 안에 끝내려고 했는데 2~3일은 걸린 것 같다. 

할 때마다 뭔가 진행이 안 된다는 생각이 나를 좀 언짢게 하기도 했다.

 

그래서 왜 2일이라는 시간이 미뤄졌는지 깊게 고민을 해봤다.

 1. 백엔드 업무를 이해 못 했나? 아니다.

 2. 하기 싫었나? 아니다. 오히려 매 순간 긴장하고 집중하여 진행했다. 집에 오면 눈이 감겨서 버틸 수가 없었다.

 

그러면 도대체 뭐냐?

생각해 보니 다른 사람들한테 도움을 주는 시간이 많아지면서 이렇게 되지 않았나 싶다.

(도움을 주기보다는 나한테 도움을 요청하는 사람이 많다.)

 

내가 아무리 컴퓨터 관련 전공자라고는 하지만, 아직 졸업도 못한 그저 학생이다.

나도 웹 개발은 거의 처음 해보는 입장이기 때문에

'네가 뭔데 도와주고 있냐...... 네거나 잘해라'라고 해도 할 말은 없다. 

 

개인적인 생각으로는 나의 것을 잘하는 것도 중요하지만,

남의 사례를 확인하고, 새롭게 배우고, 설명해 주고, 알려주는 것도

나 자신한테 큰 공부가 된다는

생각에 다른 사람들이 도움을 요청하면 할 때마다 도와줬다.

그런데 이게 생각보다 오래 걸렸나 보다.

한 사람 도와줄 때 다른 사람도 와서 계속해서 기다리고 있고,

프론트엔드를 맡으신 분이든 백엔드를 맡으신 분이든 나한테 도움을 요청했기 때문에 당연히 오래 걸릴 수밖에 없지 않은가.

또한 내 귀가 쓸 때 없이 밝아서 다른 분들이 곤경에 처하게 되면 자연스럽게 가는 것도 없지 않아 있는 것 같다.

 

도움을 주는 것을 멈출 생각이 아직은 없는 나로서는 당연히 내 업무를 마치기 위해 더 집중하고 더 노력해야 할 것이다.

그리고 도움을 주기 위해 더 공부해야 할 것이고, 이건 나 스스로의 상황을 비춰볼 때 당연한 거다.

 

3. 코드 치는 건 문제가 아니다.

 이번에도 느꼈지만 코드를 치는 것은 하나도 어렵지 않다.

어렵다고 하더라도 보고 있으면 프로그래밍 언어들마다 비슷비슷하고,

함수의 활용법도 고만고만하며, 느낌(?)을 알기 때문에 거의 다 할 수 있다. (내 착각인가......?)

그리고 안 되면 공식 문서 보면 되지.

 

 그전에 큰 그림을 잘 그리고 세부 사항까지 잘 생각한 다음에 쳐야지 완성도 있는 작품이 나온다.

이번에 하면서 중간에 DB 스키마를 변경해야 하는 상황이 자주 발생했다.

처음부터 완벽한 스키마를 내놓을 수는 없겠지만

조금의 실수가 크게 번질 수도 있기 때문에 꽤나 걱정했다.

그리고 작품을 어느 정도 완성한 지금에서 볼 때

새로운 흰 도화지에 처음부터 만들고 싶은 생각도 드는 것을 보니 조금 아쉽다는 생각을 한다.

(사실 내가 지금까지 살면서 완벽하게 마음에 든 작품이 얼마나 있을까 싶지만......)

 

다음에는 새로운 프로젝트를 할 때 조금 시간이 걸리더라도

팀원들과 더 완벽한 큰 그림을 그려보았으면 한다.

 

4. DB TABLE 간의 관계를 잘 기억하자.

 결제 API를 수요일 밤에 밤을 새워서 만들었지만 완성을 못하고

목요일에도 약 5~6시간 동안 되지 않아서 애를 먹었다.

Transaction을 사용하든 그냥 Query를 날리든

DB의 order_item_options테이블에만 데이터가 들어가지를 않았다.

에러는 발생하지 않고

affectedRows는 계속 0이라 떴다.

모든 것을

Console.log도 찍어보고 

디버깅도 해보고

query만 따로 떼어내서 workbench에서 실행도 해보고

다른 사람한테 물어보고 다 해봤는데 몰랐다.

(진짜 이건 좀 던지고 싶었다......)

그리고 하염없이 코드들을 쳐다보다가

'앗 설마?' 하는 타이밍이 왔다. (그거 하나로 약 7~8시간을 잡은 그 순간이었다.)

 

cart_item_options에서 order_item_options로 데이터를 옮기는 과정에서

cart_item_options는 Foreign Key로 cart_item_id를 갖고 있는데

carts에 있는 데이터를 먼저 삭제하고

option을 옮기는 순서로 로직을 짜다 보니 이렇게 된 것이었다.

Foreign Key에 해당하는 id값이 사라져서 이런 결과를 낳았다니......

(다른 때는 Foreign Key관련 에러라도 떴는데 이 경우는 안 떠서 참 고생했다.)

 

이걸 경험하고 나서는 DB 스키마 구조를

훨씬 더 잘 이해하고 머리에 넣어야겠다는 마음을 먹은 것 같다.

나중에 또 이런 일이 일어나면 해결은 하겠지만 화가 많이 날 것 같다.

 

 

5. 일단 만들자.

 프로젝트를 진행하면서 내가

다른 분들한테 말한 것이 있다. 

 

Q(ME): 무슨 고민이 있냐?

A: 좀 더 효율적인 코드로 만들고 싶다.

Q(ME): 생각하기 어렵지 않나? 일단 다 쪼개서 만들고 그 이후에 다시 생각해 봐라. 그러면 가능할 것이다.

A: 일단 OK.

 

이 대화를 그대로 나 자신한테 해야 할 것 같다.

한 번에 완벽하고 효율적인 코드를 만들어내는 것은 쉽지 않다.
바로 생각나면 그건 퍼펙트.

일단 코드가 복잡하고 길어지더라도

구동은 되게 전체적으로 짜보고 다시 리팩토링을 하는 것이 훨씬 효율적이라고 생각한다.

 

(이게 참 성격상 쉽지 않을 것 같지만 노력을 하란 말이다......)

 

6. 익숙해지는 것은 좋은데 이론적으로 더 공부해야 한다.

모든 게 그렇지만 어떠한 것이 이해가 안 되면

계속해서 접해서 익숙하게 만드는 것이 좋다고 생각한다.

코드도 똑같다.

 

Javascript의 비동기 처리가 되었든

Promise가 되었든

Closure개념이 되었든

정규표현식이 되었든

Agile/sprint 방식이 되었든 등등

처음에 보면 헷갈리는 게 있지만 

계속 사용하면서 아무렇지도 않게 익숙해지는 경우가 많다.

 

이때 다시 되돌아보면서 익숙해진 것에 대해 

내가 설명할 줄 아는가에 대한 질문을 나 스스로에게 하고,

없다면 이론적으로 공부하는 자세를 취해야 하지 않나 싶다.

 

+) Cloud는 무조건 사용하자

(이번에 ORACLE CLOUD를 이용해서 백엔드 서버를 이용했는데

이거 없었으면 백엔드와 프론트엔드 팀원들 모두 집에도 못 가고 고생했을 것이다.

또한 프론트와 백엔드 통신하는 데 있어서

서로의 시간을 아껴준 중요한 장비였던 것 같다. 

모든 팀원들이 나한테 와서 너무 고맙다고 할 정도였으니 말이다.)

 

+) 프론트쪽 업무도 틈틈이 공부하자

(서로 소통하는데 훨씬 도움이 된다.)(그리고 풀스택 한번 해보고 싶.....)

 

+) API Layered Pattern 기억!

-controller에서는 input으로 온 데이터에 대한 분석.

-service에서는 input으로 들어온 데이터 가공 또는 db로부터 받은 data를 가공.

 

 

 

 

 

반응형