바닐라 JS 쇼핑몰 프로젝트 후기

박재훈·2023년 3월 24일
0

회고록

목록 보기
1/1

들어가며..

3월 초부터 혼자 조금씩 뜯어보고 수정하면서 그땐 이해 못 했던 코드나 로직을 다시 보고 이해하면서 공부하니 재밌었습니다. 한편으론, 당시 해당 파트를 담당해 주었던 팀원들에게 미안한 마음과 감사한 마음이 드는 계기였습니다.
아래부터는 3주간 이것저것 뜯어고쳐보았는데, 실제 프로젝트 할 때 어려웠던 점과 이번에 리팩토링하면서 어려웠던 점 둘 다 기록으로 남기고자 글을 씁니다.

무엇을 했는가?

크게 2가지 : 디렉토리 구조 개편 그리고 번들링

가장 큰 변화가 있었고, 오랜 시간이 걸렸고 신경을 많이 썼습니다.

왜인지 왼쪽보다 오른쪽이 복잡해진 것처럼 보이지만, 왼쪽은 mypage안에 굉장히 많은 파일이 있었습니다. (세어보니 21개네요...ㄷㄷ) 그래서 그 안에서 페이지별로 폴더를 나누고 그에 맞춰 view-routing을 수정했습니다.

Pain Point 1 : 브라우저가 html문서는 가져오는데, js 나 css 파일을 못 가져옴.

원인

디렉토리 경로와 라우팅 경로가 달랐음.

해결

디렉토리 경로와 라우팅 경로 싱크를 맞춰주었음.

Pain Point 2 : 싱크를 맞춰줬는데, 정확한 html 문서를 가져오지 못함.

일례로 myapge > mypageAccount > accountUpdate 이런 식으로 개인 정보를 수정하는 페이지를 가장 아래에 구성을 했었습니다. 그런데 막상 정보수정을 누르면 수정 페이지가 아닌 다시 mypageAccount가 뜨곤 했습니다.

원인 : express.Router 에서 use() 와 get()의 차이.

공식문서를 보면서 chatGpt에게 질문을 하니 처음엔 이러한 대답을 해주었습니다.

해당 현상은 정적 파일과 라우트 경로의 중복이 원인일 가능성이 있습니다. 예를 들어, viewsRouter.use("/mypage/mypageAccount") 경로와 /mypage/mypageAccount 디렉터리에 있는 mypageAccount.html 파일 이름이 중복되어 발생할 수 있습니다.
(중략)
또한, Express.js에서는 라우트 경로가 완전히 일치하지 않아도 일부 경로가 일치하는 경우 해당 경로의 핸들러 함수가 호출될 수 있습니다.
-> 요약 :경로에서 파일명이 안 겹치게 해 봐

해결 1

경로명이 최대한 겹치지 않도록 수정해 보았습니다.
수정 전 /mypage/mypageAccount/mypageAccount
수정 후 /mypage/account/accUpdate
그렇지만 여전히 정상동작 하지 않았습니다.

해결 2

use() 메서드는 해당 경로에 대한 요청이 오면 먼저 등록된 핸들러 함수부터 처리합니다. 즉, /mypage/account/accUpdate 경로에 대한 요청이 왔을 때, /mypage/account 경로의 핸들러 함수가 먼저 호출되기 때문에 문제가 발생합니다.
해결 방법으로는, /mypage/account 경로와 /mypage/account/accUpdate 경로의 핸들러 함수를 각각 get() 메서드로 등록하여 순서를 명확하게 지정해 주는 것입니다.
-> 요약 : use 말고 get 써봐

(마치 리액트 라우팅에서 exact를 써주는 것과 같은 원리였습니다.)
use() -> get()으로 수정하니 정상동작하며 해결되었습니다.

Pain Point 3 : 동적 페이지 구성과 이벤트 바인딩

현상

동적으로 구성한 요소에 이벤트를 걸면 항상 해당 요소를 찾을 수 없다는 에러가 발생.

원인

단순히 addEventListener를 적용할 요소가 없기 때문이다.

해결

동적 페이지를 구성하는 함수 블록 내에서 이벤트를 작성해서 바인딩해 주었습니다.

const productList = document.querySelector(".section_box");

async function insertProductElement() {
  const products = await Api.get("/api/products"); //상품정보를 받아옴

  products.forEach((product) => {
    const brand = product.brand;
    const name = product.name;
	
    productList.insertAdjacentHTML(
      "beforeend",
      `
      <section class="pd_block" id="${category}">
      <img src="${img}"class="box ${updateProduct}"/>
      <article class="pd_text">
        <div class="pd_box">
          <p class="pd_brd" id="${brand}">${brand}</p>
          <p class="pd_name" id="${name}">${name}</p>
        </div>
      </article>
    </section>
      `
      //받아온 정보를 렌더링
      
      ref[updateProduct].addEventListener("click", (event) =>
      updateProductFunc(event, product)
    );
    
    );

    const pdBox = document.querySelector(`.pd_box`);

    pdBox.addEventListener("click", () =>
      console.log("Hi");
    );
     //렌더링한 엘리먼트에 이벤트 걸기
  });
}

async function updateProductFunc(e, product) {
  e.preventDefault();

  window.location.assign(`/productDetail/${product.num}`);
}

다른 해결 방법

또 다른 방법으로는 정적으로 작성된 부모 요소에 이벤트를 거는 방법과 상황에 따라 다르겠지만 script 태그에 defer 속성을 넣는 방법 등이 있었습니다.

Pain Point 4 : 번들링

현상

먼저 저희 팀은 모든 페이지를 정적으로 만들었습니다. 그리고 기능별로 js 문서를 만들고 하나하나 연결했습니다. 하지만 저는 좀 더 깔끔하고 빠르게 만들고 싶었습니다.

해결: 필요한 기능과 엘리먼트의 모듈화, 컴포넌트화 그리고 번들링

catergory와 같은 기능을 위한 js들과 header, footer.js 들을 모두 home.js 에서 import 해오도록 수정하고 나니 아래처럼 깔끔한 구조를 가지게 되었습니다.

그리고 번들링까지 하고 나니 브라우저 네트워크 탭에서 js를 다운로드하는 개수가 줄었고, 로드되는 속도가 많이 감소했습니다.

모듈화 전
DOMContentLoaded : 1.40s / Load : 1.60s
모듈화 후
DOMContentLoaded : 415ms / Load : 649ms
번들링 후
DOMContentLoaded : 334ms / Load : 402ms

현상 : footer가 하단에 고정되지 않음.

원인

만약 특별한 속성을 주지 않았다면 당연한 결과입니다.

해결

그래서 특별한 속성을 부여했습니다. html과 body는 높이 100%라는 속성을 주고,
body 태그 안에 머리 몸통 발 3단계로 구분하여 flex를 세로 정렬하는 속성을 주었습니다.
그리곤 가운데 있는 section에 flex : 1 속성을 주면 100%의 높이 전부를 section이 가지게 됩니다.

      <html style="height: 100%;">
        <body style="height: 100%;">
          <div style="display: flex; flex-direction: column;">
            <header></header>
            <section style="flex:1"></section>
            <footer></footer>
          </div>
        </body>
      </html>

참고 : https://youtu.be/who42wBr1ns,
flex를 잘모르신다면 https://studiomeal.com/archives/197

성과

1. 깔끔한 디렉터리 구조

2. 코드 가독성 상승

3. 페이지 로딩 속도 단축 (DOMContentLoaded : 1.40s -> 334ms)

4. 구글 라이팅 하우스 Performance (61 -> 85) / Best Practices (75 -> 83)

소감

아직도 손보고 싶은 부분이 너무나도 많습니다. 성능 최적화, 반응형 등등 많지만 일단 여기서 마무리해보았습니다. 진행하면서 브라우저의 렌더링 과정을 많이 공부하게 되었고, CS 지식이 필요하다는 것을 깨닫는 과정이었습니다.
이후에 최적화를 마치고 나면 React로 마이그레이션까지 해보려고 합니다. 여유가 된다면 TS까지 하려고 합니다....
그리고 코딩과 별개로 글 쓰는 게 참 어렵고 번거롭고... 그렇구나... 난 정말 말을 조리 있게 못 한다... 는 것을 많이 느꼈습니다. 꾸준히 글을 쓰려했지만... 쉽지 않았습니다... 이상 후기를 마칩니다. 감사합니다.

더 자세한 코드는 여기서...😺

profile
신입 개발자

0개의 댓글