Journal/Today I Learned

TIL - 2022.03.03 목요일

쭈꾸미 2022. 3. 3. 17:33

이제까지 배운 것

1. 여러개의 요소에 useRef를 병렬로 적용하는 방법

위와 같은 페이지에서 상단의 서브메뉴를 눌렀을 때 페이지를 리로드하지 않고 내용 부분의 컨텐츠만 교체하고 싶었다. 레이아웃을 이용하자니 pageProps 내에 뿌려지는 컨텐츠 안에 레이아웃을 하나 더 만들어서 넣는 방법을 모르겠고. 한동안 고민하다가, 결국 메뉴 버튼와 내용 부분의 index를 연결해서 수동으로 display를 컨트롤하는 방법으로 해결했다. 그것을 위해 필요한 DOM 조작은 useRef를 배열로 넣어서 처리 완료.

 

<!--서브메뉴 버튼 부분-->
<Mypage.ContentsHead>
    <ul>
      <li
        onClick={props.onClickDivSwitch(0, 3)}
        ref={(el) => (props.buttonRef.current[0] = el)}
      >
        <span>내가 산 물건</span>
      </li>
      <li
        onClick={props.onClickDivSwitch(1, 3)}
        ref={(el) => (props.buttonRef.current[1] = el)}
      >
        <span>내가 파는 물건</span>
      </li>
      <li
        onClick={props.onClickDivSwitch(2, 3)}
        ref={(el) => (props.buttonRef.current[2] = el)}
      >
        <span>포인트 충전 내역</span>
      </li>
    </ul>
</Mypage.ContentsHead>
<!--컨텐츠 부분-->
<Mypage.ContentsBoxInner
	ref={(el) => (props.divRef.current[0] = el)}
	>
    <Mypage.ContentsTitle>
    	<h3>내가 산 물건</h3>
    </Mypage.ContentsTitle>
    <Mypage.ContentsItem>
    	컨텐츠가 들어가는 부분
    </Mypage.ContentsItem>
</Mypage.ContentsBoxInner>
<Mypage.ContentsBoxInner
	ref={(el) => (props.divRef.current[1] = el)}
	style={{ display: "none" }}
	>
    <Mypage.ContentsTitle>
    	<h3>내가 파는 물건</h3>
    </Mypage.ContentsTitle>
    <Mypage.ContentsItem>
    	컨텐츠가 들어가는 부분
    </Mypage.ContentsItem>
</Mypage.ContentsBoxInner>
<Mypage.ContentsBoxInner
	ref={(el) => (props.divRef.current[2] = el)}
	style={{ display: "none" }}
    >
    <Mypage.ContentsTitle>
    	<h3>포인트 충전 내역</h3>
    </Mypage.ContentsTitle>
    <Mypage.ContentsItem>
    	컨텐츠가 들어가는 부분
    </Mypage.ContentsItem>
</Mypage.ContentsBoxInner>
// javascript 부분
const onClickDivSwitch = (index, length) => () => {
    const targetDiv = divRef.current[index];
    const targetButton = buttonRef.current[index];

    for (let i = 0; i < length; i++) {
        const allDiv = divRef.current[i];
        const allButton = buttonRef.current[i];
        allDiv.style.display = "none";
        allButton.classList.remove("active");
    }

    targetDiv.style.display = "block";
    targetButton.classList.add("active");
};

이 코드를 응용하면 좀 더 다양한 레이아웃을 구현할 수 있을 것 같다. 이 방법의 아쉬운 점이라면 코드 수가 많이 길어진다는 부분인데, 어떻게 하면 이 요소를 컴포넌트로 분리해서 재사용성을 높일 수 있을지 고민해봐야겠다.

 

2. jest, cypress를 이용한 테스트 코드 학습

테스트 코드란?

말 그대로 테스트하는 코드. 대상이 되는 코드가 제대로 동작하는지, 오류 없이 제 기능을 하고 있는지 검사하는 코드이다.

 

서비스에 발생한 오류를 수정하거나 새로운 기능을 더하는 작업을 거친 뒤, 그로 인해 어떠한 Side Effect가 발생했을지는 아무도 예상하지 못한다. 그래서 라이브 서버에 수정된 부분을 병합하기 전 서비스가 제대로 동작하고 있는지 검사해주기 위해서도 테스트 코드가 필요하다. 잘 작성된 테스트 코드와 테스트의 자동화는 서비스의 안정성을 높이는데에 크게 도움이 된다!

(husky를 이용해 테스트를 통과하지 못하면 git commit을 못하도록 막는 것도 가능함)

 

테스트 코드 작성 시점

  1. 처음 개발부터 테스트 코드를 같이 작성한다.
    • 이상적인 케이스지만, 이 경우 개발 기간이 그만큼 늘어난다.
  2. 첫 개발 및 서비스 공개 후 마케팅 팀이 홍보하는 기간에 테스트 코드를 작성한다.
    • 오픈은 완료했지만 아직 서비스 이용률이 높지 않아서 개발팀의 업무가 줄어든 시점에 테스트 코드를 작성하면 한정된 인적 자원을 효율적으로 활용할 수 있다.
  3. 개발 전에 테스트 코드를 먼저 작성하고 프로그래밍한다. (TDD / Test Driven Development / 테스트 주도 개발)

 

테스트 코드의 종류

  1. 버튼 클릭과 같은 기능 단위 테스트
  2. 여러 기능을 한꺼번에 점검하는 통합 테스트
  3. 접속, 로그인, 구매 등 시나리오가 있는 E2E 테스트

Jest/Cypress등의 프레임워크를 이용하여 테스트를 진행하게 되는데, Jest는 단위 테스트에 좋고 Cypress는 통합 테스트 및 E2E 테스트에 사용하기 좋다.

 

자세한 설치 및 이용 방법은 사용하고 있는 프레임워크/라이브러리나 Jest, Cypress의 공식 문서를 참고할 것.

나는 Next.js를 이용해서 프로젝트를 작업하고 있기 때문에 Next.js의 Testing 페이지를 참고했다.

 

https://nextjs.org/docs/testing

 

Testing | Next.js

Learn how to set up Next.js with three commonly used testing tools — Cypress, Playwright, Jest, and React Testing Library.

nextjs.org

 

앞으로 할 것

- 핵심 기능 구현은 대강 마무리 한 것 같다. 이제 미뤄두었던 UI / 랜딩페이지 작업을 하자.

- 이미지 preload 구현해서 스토리지 공간 절약

- apollo-cache를 이용해서 API 통신 성능 향상

- alertBar가 on/off 될 때마다 페이지 전체가 리렌더링 되는 문제가 있는데, 메모이제이션을 이용해서 해당 문제 해결