현재 수강 중인 엘리스에서 1차 프로젝트를 끝냈습니다. 총 2주간 프로젝트를 진행했고, 프로젝트 주제는 모두 동일하게 쇼핑몰 통일되었지만 그 안에서 팀별로 상세 기획은 서로 다르게 하는 형식이었습니다. 저희 팀은 랭킹 닭컴과 같이 건강식품 쇼핑몰로 선택했습니다.
프로젝트 사이트는 아래와 같습니다 ↓↓↓
사이트: http://kdt-sw3-team13.elicecoding.com/
gitHub: https://github.com/team-13-beta/ecommercesite
FE: HTML
,CSS
,JavaScript
,Bulma
BE: Node.js
, Express
, MongoDB
, VM
그간의 경험에서 느꼈던 것은 너무 당연하지만 초반 기획을 할 때 각자 합의가 필요한 내용에 대해 사전에 합의가 있어야 하고 그것이 문서화되어 있어야 한다는 것이었습니다.
그래서 팀 회의를 할 때 기획 이후에 제일 처음 한 것이 구현 사항 정리와 API 명세 작성이었습니다.
구현에 필요한 API 목록 정리를 마친 뒤, 각자 역할 분담을 통해 구현할 페이지들을 나눴습니다. 저는 관리자 페이지를 구현하는 역할이었고, 예전에 과제 테스트에서 VanillaJS로 SPA를 구현하는 과제를 받은 적이 있어서 연습할 겸 SPA를 통해 관리자 페이지를 제작했습니다.
제가 작성한 페이지의 폴더 구조는 다음과 같습니다.
admin // 관리자 폴더
┣ categories // 카테고리 폴더
┃ ┗ category.js
┣ components // 컴포넌트 폴더
┃ ┣ category
┃ ┃ ┗ categoryHeader.js
┃ ┣ order
┃ ┃ ┗ orderTemplate.js
┃ ┣ product
┃ ┃ ┣ productHeader.js
┃ ┃ ┗ productTemplate.js
┃ ┣ modal.js
┃ ┗ tableTemplate.js
┣ mockData // MockData 폴더
┃ ┣ categoryData.json
┃ ┣ orderData.json
┃ ┗ productData.json
┣ orders // 주문 폴더
┃ ┣ order.js
┃ ┗ orderDetail.js
┣ products // 상품 폴더
┃ ┣ product.js
┃ ┗ productDetail.js
┣ admin.css
┣ admin.html
┣ app.js // 렌더링이 이루어지는 폴더
┗ index.js
app.js
파일에서 state
가 전역적으로 관리되고 각각의 컴포넌트들에 state
가 전달되는 방식으로 기능을 구현했습니다. category, product, order
의 페이지 구현이 필요했기에 app.js
에서 각각의 객체의 상태값이 변경된다면 render
하는 형식으로 구현했습니다. (자세한 코드는 github에서 보실 수 있습니다.)
SPA로 구현하면서 크게 3가지 이슈가 발생했는데 하나씩 보겠습니다.
위 영상과 같이 주문 상세에서 상태 변경 후 다시 접속했을 때 이벤트가 여러 번 겹쳐서 중복되는 현상이 있었습니다. 해당 이슈에 대해 고민을 하다가 orderDetail.js
에서 parent element
에 이벤트를 등록하는 과정에서 버그가 발생한 것을 알 수 있었습니다.
인스턴스가 생성되고 페이지가 렌더링 될 때마다 init 메서드를 실행하게 되는데, 제가 parent element
에 click
, change
등의 이벤트를 등록하는 코드를 init
메서드에서 작성한 것이었습니다. 즉, parent element
는 클로저로 인해 계속해서 참조가 되고 있는데, init 메서드가 실행될 때마다 해당 element
에 이벤트가 계속해서 등록이 된 것이었습니다.
해당 이슈를 겪고 난 뒤, 이벤트 버블링과 클로저(엘리먼트 생명 주기)에 대해 좀 더 알게 되었습니다.
VanillaJS의 한계인가 싶은 느낌도 듭니다. BE를 Node.js
로 작성하면서 각각의 url에 접속하게 된다면 알맞은 html 파일을 실행시키도록 코드를 작성했습니다. 하지만 admin
의 경우에는 admin.html
이라는 한 개의 파일에서 코드 작성이 이루어졌기 때문에 category, order, product
를 담당하는 html
파일이 존재하지 않습니다. 따라서, 일단 /admin/*
경로로 접근했을 때에는 일단 /admin
으로 redirect 시킨 뒤, order
페이지로 가도록 코드를 작성했습니다.
하지만, /admin/order
이렇게 직접적으로 입력했을 때, 해당 파일을 불러올 수 있게끔 할 수 있을 것 같으면서도 이게 쉽지 않은 것 같아서 고민이었습니다. (추후에 백엔드 하시는 분과 한번 합을 맞춰봐야 할 것 같습니다)
프로그램 기능 중에 이미지를 올리는 기능이 필요했습니다. 관리자 입장에서 이미지를 올리는 경우에는 컴퓨터 파일에서 직접 올린다고 생각을 하고, input type="file"
의 형식으로 element
를 선언한 뒤 change
또는 input
이벤트를 등록했는데, 해당 이벤트 등록이 되지 않는 것입니다...
인스턴스로 만든 객체들에게는 모두 parent element
가 있고, 해당 element
에 이벤트를 구독하도록 해서 중복 코드를 제거했습니다 (이벤트 위임) 해당 코드에서 말하는 this.$element
에 click
이벤트를 등록한 뒤, 또다시 change
, input
이벤트를 등록했지만, 파일 선택이라는 부분을 클릭하면 click
이벤트만 발생이 되고 change
와 input
이벤트는 발생이 되지 않았습니다.
그렇다면, input
이벤트에 click
이벤트를 할당하면 되지 않냐라는 말이 나올 수 있지만,MDN에 따르면 type="file"
인 경우에는 input
이나 change
이벤트만을 구독할 수 있다고 나와 있습니다. 즉, click
이벤트로 이미지 삽입이 불가능한데, parent Element
가 이미 click
이벤트를 구독하고 있어서 다른 이벤트가 먹히지 않는다는 것입니다.
해당 이슈 해결을 위해 이벤트 위임을 하지 않고 새롭게 화면에 paint
될 때마다 이벤트 등록을 했습니다.
이미지 src를 DB
에 등록해서 사용하면 좋겠지만, 이미지 src가 너무 길어서 비효율 적이라는 생각을 했습니다. 따라서 AWS에 s-3를 사용해서, 해당 이미지의 key 값을 DB에 저장하고 DB에서 이미지를 불러올 때, 해당 key 값을 통해 이미지를 불러오는 방식을 사용했습니다.
s-3에서 이미지 수정 기능을 제공하는 것을 찾을 수 없었기 때문에, 이미지를 수정하는 경우는 해당 이미지를 삭제 후 재등록하는 형식으로 진행했습니다.
2주라는 시간 동안 기획부터 개발까지 해야 하는 살짝 빠듯한 일정인데다가, 프로젝트에서 처음 구현하는 SPA 방식으로 진행했기 때문에 도전 과제의 느낌이 강했습니다. 하지만 성공적으로 프로젝트를 마칠 수 있었고, VanillaJS로 SPA 구현하는 문제에 대해서는 어느 정도 실마리를 잡은 것 같아서 기분이 좋습니다.
다만, 모든 프로젝트가 그렇듯이 기획을 제대로 하고 가는 것이 중요하다는 것을 다시금 깨닫게 되었습니다. 물론, 개발을 하다 보면 예기치 못한 제한 사항이나 요구사항이 발생할 수도 있고 그에 따라 기획이 변경될 수도 있지만, 제일 처음에 꼼꼼하게 생각을 하지 않고 얼렁뚱땅 넘어가게 된다면 배로 힘들 수 있다는 것을 다시금 깨닫게 되었습니다.
저희 팀의 경우에는 처음에 기획과 구현 요구사항을 정리하고 그에 맞춰 API 명세서를 작성했음에도, 좀 더 구체적으로 work-flow를 작성했다면 같은 일을 반복하는 일이 줄었을 텐데 하는 아쉬움이 있었습니다. 예상치 못한 work-flow가 등장하고, 각자의 역량과 구현하고자 하는 방식, 이미지가 달랐기 때문에 초반 API 명세와 나중에 명세서를 보면 추가된 기능들이 많이 존재했습니다. 또한 추후 협의를 하기 위해 초안만 작성된 않은 명세서 들과 비대면으로 프로젝트를 진행한 점이 즉각적인 피드백이 오지 않고, 반영이 되지 않은 점에서 어느 정도 시간 누수가 있었다고 생각합니다.
사실 위에서 언급한 문제들을 잘 조율하고, 본인의 역량 내에서 최고의 효율을 내는 것이 중요한 점이지만, 어느 정도 아쉬운 점이 남는 것은 개인 역량의 한계도 어느 정도 있었다고 생각을 하며 좀 더 나은 개발자가 되기 위해 노력해야겠다는 생각을 하게 되었습니다.