영화 리뷰 - 웹앱 회고

회고는 프로젝트 단위로 진행되며 KPT 방법으로 진행됩니다.

프로젝트 링크.

STEP1 PR

STEP2 PR

프로젝트를 시작하며.

마지막 과제를 마치고 다시 회고하게되었다.

이번 미션의 키워드는 비동기이고 웹 앱으로 진행을 하였다.

그동안 Domain과 View를 나눴던 것에 대한 성과를 보여주고자 했다. 웹의 사용자 기반의Cypress기반 E2E 테스트를 진행하며 TDD를 해보았는데 End-to-End에서의 디테일에 대한 부분에도 신경을 써보았다.

고민해본 문제

DOM에 접근 최소화

  1. DOM에는 하나씩 Element를 만들어넣어줄 수 있다.

이렇게하면 N번만큼 DOM에 접근해야한다.

/  showSkeleton() {
    for (let i = 0; i < 20; i++) {
      const skeletonItem = document.createElement("li");
      skeletonItem.classList.add("skeleton-item");
      skeletonItem.innerHTML = /*html */ `
            <div class="item-card">
                <div class="item-thumbnail skeleton"></div>
                <div class="item-title skeleton"></div>
                <div class="item-score skeleton"></div>
            </div>
        `;
      this.itemList.appendChild(skeletonItem);
    }
  }

  1. Text를 만들어준 다음 한 번에 DOM에 넣어준다.

이 방법을 쓰면 요구조건을 맞출 수 있다. 하지만 특정 element 내부에 추가적으로 작업을 하려니 가독성이 떨어진다.

showSkeleton() {
    const skeletonElement = Array.from(
      { length: 20 },
      () => /*html */ `
        <li class="skeleton-item">
            <div class="item-card">
                <div class="item-thumbnail skeleton"></div>
                <div class="item-title skeleton"></div>
                <div class="item-score skeleton"></div>
            </div>
        </li>
    `
    ).join("");
    this.itemList.innerHTML += skeletonElement;
}

  1. DocumentFragment 사용하여 한 번에 DOM에 넣어준다.

2번째랑 다른 점은 가상 메모리에 담아뒀다가 Element에 한 번만 넣어준다는 점이다.

 showSkeleton() {   
    const fragment = document.createDocumentFragment();
    Array.from({ length: 20 }).forEach(() => {
      const li = document.createElement("li");
      li.className = "skeleton-item";

      const itemCard = document.createElement("div");
      itemCard.className = "item-card";

      const thumbnail = document.createElement("div");
      thumbnail.className = "item-thumbnail skeleton";

      const title = document.createElement("div");
      title.className = "item-title skeleton";

      const score = document.createElement("div");
      score.className = "item-score skeleton";

      itemCard.appendChild(thumbnail);
      itemCard.appendChild(title);
      itemCard.appendChild(score);
      li.appendChild(itemCard);
      fragment.appendChild(li);
    });

    this.itemList.appendChild(fragment);
}

개인적으로 성능 상으로 2번과 3번 방법을 비교해서 성능 비교 글을 써보고 싶은데,

가독성이나 특정 Element 내부에 다른 Elements를 넣는 요구조건을 맞추기는 3번을 선호하게 될 것 같다.

KPT.

Keep.

  • commit lint를 지키며 기능 단위로 commit을 올렸다.(전 회고에서 유지할 부분)

  • Domain과 View는 책임을 나누어 진행하였다.(전 회고에서 유지할 부분)

  • 리뷰 시 리뷰어님을 설득한 나의 근거를 준비한다.(전 회고에서 유지할 부분)

  • 항상 여러 가지 방법을 고민해본다.

Problem.

  • 도메인 에러만이 아니라 API가 생기면서 에러처리의 복잡도가 올라갔다.

  • 에러를 이용해서 유저에게 나타내는 부분이 콘솔과는 고민해야할 부분이 증가했다.

Try.

  • API 에러를 따로 관리하고 필요하다면 API도 하나의 도메인처럼 따로 분리할 수 있었다.

  • 콘솔은 단순 Text를 이용하고 다시 입력받는 부분을 신경썼지만, Modal과 같은 방식을 통해 기존 화면에서 어떻게 표현할 수 있을지 고민하였다.(오히려 표현의 자유도가 올라간 것 같다.)

프로젝트를 마치며.

리뷰어님들의 꼼꼼한 리뷰로 가독성과 유저경험에 대해 더 고민해볼 수 있었고,

특히 이번 과제에서는 에러처리와 E2E 테스트에 대해서 고민해볼 수 있는 시간이었다. 이번 과제에서 진행했던 부분 중 일부는 복잡도가 더 올라간 프로젝트에서 적용시켜보고자 한다.

Next Step.

마지막 과제까지 7주간의 세션과 함께 끝이 났다.

개인적으로는 보충 STEP부분 구현은 셀프로 진행하며 마무리하고 같은 Nextstep의 React도 Fork를 떠서 진행해볼 예정이다.

Last updated