[회고록] VanillaJS 과제 돌이켜보기 (feat. 처음부터 현재까지)

SUNG JE KIM·2023년 4월 4일
1
post-thumbnail

운이 좋게도 지원한 회사에서 서류 합격을 받아 과제 전형을 진행하게 되었다.
HTML, CSS, JS(ES6+)만을 이용해서 요구 사항, 디자인에 맞게 구현을 해내야 했다.
주요 요구 사항에는 반응형, Cross Browsing 정도였다.

- React를 먼저 접해본 사람.


물론 동아리 활동을 진행하면서 VanillaJS를 이용해 TODOList를 만들었다.
그것이 내 인생 중에서 처음 개발이자, 처음으로 브라우저와의 소통이였다.
지금 와서 보면 정말 간단하게 그지 없는 TODOList였다.
(TODOList 만들기 GitHub)
그런 식으로 일주 정도인지 이주 정도인지 TODOList 작업을 하고 바로 React로 미니프로젝트를 했었다.

사실 React를 배우기 전에 몇몇은 "React가 어렵다.", "React를 배우기 힘들 거 같다", '너무 어렵지 않을까?'라는 의견을 종종 들어왔다.
하지만 나는 신기술에 배우기 최적화 되어 있는지, 개인적으로 위와 같은 생각은 들지 않고, 아래와 같은 생각이 들었다.

"우리가 개발하기 편하라고 React 같은 게 나오지 않았을까?"

"지금보다 불편하고 어려우면 왜 쓰지?"

"오히려 좋겠지~~"

그렇게 React와 함께 여러 프레임워크, 라이브러리 등등...같이 사용하며 미니 프로젝트, 본 프로젝트, 개인 프로젝트를 진행했다.

그리고 React를 이용한 프로젝트들을 주력 삼아서 회사에 지원했는데, 과제를 VanillaJS로 받았다.
정말이지 요구 사항과 디자인을 보자마자 React로 어떻게 해야 하는지 보였다.

그게 문제였다. VanillaJS로는 어떻게 해야 하는지 생각 조차나지 않았고, 'React로 이건 이렇게, 저건 저렇게'라는 생각만 들었다.

- CRA vs ???


우선 그래서 정신 차리고 먼저 든 생각이 'Cross Browsing 테스트를 어떻게 하지?'라는 생각이 먼저 들었다.
'어떻게 하긴 배포하면 정확하겠지'하고 최근에 AWS 배포 관련 글 쓰면서 공회전 중인 EC2가 있어서 거기에 코드를 띄워서 확인하기로 했다.
근데 VanillaJS를 어떻게 세팅해야 하는지 생각하는데 뇌가 멈췄다.
'Bundler가 없는데 local에서 확인하는 건 그렇다 치고, 어떻게 EC2에 코드를 띄우지...?'라는 생각이 들어서 webpack과 eslint를 우선 설정하였다.

기초 틀은 아래의 링크를 참고하여 설정하고, 내 폴더구조와 EC2 환경 설정에 맞게 수정하였다.

https://yujo11.github.io/javascript/Vanilla%20JS%20%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%20%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0/

성공적으로 설정을 한 후에, API 요청을 먼저 진행해서 응답을 확인하고 배포를 하고 또 확인했는데 어랍쇼?
브라우저로 확인을 해보니까 좌상단에 'Invalid host header'라고 띡 하나 떠있고 네트워크 요청이 가지 않고 있었다. FrontEnd가 BackEnd를 바라보고 있지 않아서 생기는 이슈였다.
추측컨데, NginX 설정 중에서 upstream 설정을 통해서 서버와 연결을 해야 하는데 급한대로 NginX를 삭제했다.
그리고 EC2 IP를 통해서 확인해보니 잘 되는 것을 확인했다.

- useState vs ???

부제: react-router-dom vs ???


컴포넌트들을 거의 만들고 이제 리스트 중에 Card 하나를 누르면, 해당 Card 정보를 Details 컴포넌트에 띄워야 했다.
우선 제일 먼저 든 생각이 'Card를 누르면 URL을 ID로 Routing을 시키고 ID 값을 쿼리로 붙이자!!!'해서 'localhost:3000/id?id=123123123'과 같은 식으로 구현을 하려고 했다.
근데 웬 걸 'localhost:3000/id'가 되자 HTML, CSS, JS를 해당 디렉토리에서 찾아내지 못해서 아래와 같은 오류를 보였다.

그래서 아래 코드를 통해서 'localhost:3000/?id=123123123' 식으로 했는데 Card를 누르면 URL이 바뀌면서 새로고침이 되었다. e.preventDefault()를 이용해도 새로고침이 되었다.

const searchQuery = new URLSearchParams({ id: res.id });
window.location.search = searchQuery;

여기서 새로고침이 되는 이슈가 얼마나 치명적이냐면, 새로고침 때문에 GET API 요청을 다시 해서 상태를 초기값으로 되돌려버린다.

그래서 window.history.pushState라는 함수가 있어서 이용해 라우팅을 해보려고 했다.
정상적으로 새로고침 없이 작동이 되고, 값을 가져오는데도 문제가 없지만 정말 뭔가 맘에 들지 않는 방법이였다.

window.history.pushState({ path: res.id }, "", "?id=" + res.id);

const searchQueryValue = new URLSearchParams(window.location.search).get("id");

pushState 함수를 쓸 때 가독성이 개인적으로 맘에 들지 않았다. 뭔가 URL 관련 코드라는 건 알겠는데, 한눈에 안 들어오는 느낌이랄까....?

그래서 useState를 구현하기로 했다.

생각보다 별 거 없었던 거 같다. useState를 간단하게나마 구현을 해서 그런지 기분이 좀 좋았다 ^___^

import Details from "../components/reservationDetails";

let initialState = null;

const useState = (state) => {
  if (initialState === null) initialState = state;

  const handler = (newState) => {
    initialState = newState;
    Details();
  };

  return {
    state: initialState,
    handler: handler,
  };
};

- useEffect vs ???


브라우저의 사이즈를 변동을 감지하기 위해서 React의 useEffect를 이용해서 아래와 같이 구현한 적이 있다.

function useCheckDeviceSize() {
  const dispatch = useDispatch();
  const changeDeviceSize = () => {
    dispatch(
      getDeviceSize(
        (() => ({
          deviceWidth: window.innerWidth,
          deviceHeight: window.innerHeight,
        }))()
      )
    );
  };

  useEffect(() => {
    changeDeviceSize();
    window.addEventListener("resize", changeDeviceSize);
    return () => {
      changeDeviceSize();
      window.removeEventListener("resize", changeDeviceSize);
    };
  });
}

위와 같은 코드를 VanillaJS를 이용해서 구현해야 하는데, 어찌 해야 하는지 참 막막했다.
근데 구글링을 해보니 matchMedia라는 것이 있어서 그것을 사용해서 아래와 같이 구현했다.
matchMedia의 와 resize를 이용한 차이점이 궁금해서 두 코드 모두 사용해서 브라우저의 사이즈를 줄여가며 테스트를 해보았다.

const mediaQuery = window.matchMedia("(max-width: 720px)");

function windowMatchMedia(e) {
  if (e.matches) console.log("in MatchMedia: ", "SmallScreens");
  else console.log("in MatchMedia: ", "LargeScreens");
}
mediaQuery.addEventListener("change", windowMatchMedia);

/** ---------------------------------------------------------------- */

function windowResize() {
  if (window.innerWidth < 720) console.log("in resize: ", "SmallScreens");
  else console.log("in resize: ", "LargeScreens");
}
window.addEventListener("resize", windowResize);

matchMedia와 resize 비교 결과

아래에 더 자세한 수치 비교 결과 또한 있음. 또한 그 수치가 다소 편향되어 있을 수 있습니다.

결과 사진만 보아도 resize 함수의 실행빈도가 매우 많은 것을 알 수 있다.
matchMedia는 addEventListener의 함수를 설정해둔 기준값을 통과할 때만 실행시키지만, resize는 기준값을 통과하지 않아도 addEventListener의 함수를 실행시킨다.
그리고 968px에서 51px까지 왔다 갔다 한 번해서 프로파일링을 해봤다.

resize 테스트(51px~968px)

matchMedia 테스트(51px~968px)


크게 뭐가 많지 않은 어플리케이션임에도 불구하고 matchMedia가 성능상으로 좀 더 유의미하게 좋아보였다.

이 부분에 대해서 좀 더 다른 생각이나 결과가 다르신 분이 있다면 댓글 남겨주시면 감사하겠습니다!!

- React vs VanillaJS


개발을 한지 1년 정도 되어가는데, 지표를 나타내보자면 아래와 같이 그 중에서 React가 정말 많이 차지 할 정도로 함께한 시간이 많은 라이브러리다.
그리고 React만 써서 그런지, VanillaJS를 이용하면서 React Hook의 필요성도 크게 느끼고, React Hook을 이용한 개발이 나에게 참 많이 녹아든 거 같아 아쉬웠다... 무언가에 갇혀있는 듯한 느낌이랄까.

그렇지만, 또는 그래서인지 이번을 계기로 VanillaJS의 매력을 역시 튜닝의 끝은 순정인가 싶을 정도로 큰 매력을 느꼈다.
React는 양산형 공장 처럼 개발하는 느낌이라면, VanillaJS는 그 '한땀한땀' 개발하는 느낌이 크게 들어서 좋았다.
VanillaJS를 쓰면서 머리 빠지는 느낌이 들었는데, 그 느낌이 좋은 거일지도....

긴 글 읽어주셔서 감사합니다.

0개의 댓글