[TIL 220127] babel.config.js vs .babelrc의 차이점, 아이템 리스트에서 이벤트 위임 처리

Ko Seoyoung·2022년 1월 27일
1

✅ Today I Learned

목록 보기
16/16

1. babel.config.js vs .babelrc

나는 보통 프로젝트 초기 환경설정을 할 때 이전 나의 프로젝트를 참고하거나 다른 사람의 프로젝트를 참고했다.

그러다보니 어떤 프로젝트는 babel 설정 파일 포맷을 babel.config.js, babel.config.json으로도 하고 .babelrc를 사용하기도 한 걸 발견했다.

어쩌다 .babelrc을 사용했는진 모르겠다. 아마 잘못사용한것이 아닌가 싶어 세가지 포맷에 어떤 차이가 있는지 알아보았다.


바벨은 두 가지 설정 파일 포맷을 갖고, 포맷에 따라 용도가 다르다.
두 가지 파일 포맷은 단독으로 사용할 수도, 둘 다 사용할 수도 있다.

1) 프로젝트 전체 구성 :

babel.config.(json|js)

프로젝트 전체 구성시 사용되는 babel.config.json, babel.config.js 등은
여러 패키지 디렉토리를 가진 프로젝트에서 하나의 바벨 설정을 할 때 사용된다.

2) 상대파일 구성

.babelrc

파일/디렉토리의 하위 집합에서 특정 변환/플러그인을 실행하려는 경우에 유용하다다.
프로젝트 내에 서드파티 라이브러리가 바벨에 의해 변환되지 않기를 원할 수도 때문이다.

바벨은 컴파일 되는 “filename” 부터 폴더 구조를 따라 올라가며 .babelrc 파일을 로드한다.

package.json 파일 안에 정의된 “babel” key

{
  "name": "my-package",
  "version": "1.0.0",
  "babel": {
    "presets": [ ... ],
    "plugins": [ ... ],
  }
}

.js vs .json

바벨 설정 파일은 .js.json 두 가지 확장자를 사용할 수 있다.

.js를 사용하면 바벨 구성 api가 노출되는데 (https://babeljs.io/docs/en/config-files#config-function-api) 이 경우 캐싱과 관련하여 복잡성이 증가하게된다.

따라서 대부분의 케이스에서 .json을 사용하는게 더 낫다고 한다.


2. 아이템 리스트, 이벤트 위임처리로 리팩토링

나는 대부분 클릭 이벤트를 각 컴포넌트에 달곤했다. 그래서 컴포넌트에는 매번 onClick을 props로 갖고 있었다. 하지만 아이템을 여러개 갖는 아이템 리스트 컴포넌트에서 각 아이템 마다 클릭 이벤트에 반응하는 이벤트 핸들러가 달려있다면? 이는 많은 DOM 요소에 이벤트 핸들러를 등록하기 때문에 성능 저하의 원인이 될 수 있다.

따라서 이벤트 위임을 적극 활용하기로 다짐했다.

이벤트 위임이란?

이벤트 위임은 여러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법을 말한다.

이렇게 상위 DOM 요소가 하위 요소에 대한 이벤트 발생을 감지 할 수 있는 이유는 버블링이라는 개념 때문이다.

버블링

이벤트가 요소에서 발생하면 먼저 해당 요소에서 핸들러를 실행한 다음 상위 요소에서 실행한 다음 다른 상위 요소에서 계속 실행하는 것.

이벤트 위임 적용하기

이벤트 위임 적용 전 코드

  return (
    <Wrapper>
      {items.map((item) => (
        <Item
          key={item.id}
          {...item}
          selected={selectedId === item.id}
          onClick={() => onItemClick(item.id)}
          />
      ))}
    </Wrapper>)
}

이벤트 위임 적용 후

  const handleItemClick = (e: MouseEvent) => {
    // .item을 선택자로 갖는 가장 가까운 요소 찾기
    const target: HTMLElement | null = (e.target as HTMLElement).closest(
      '.item'
    );
    if (target) {
      const itemId = parseInt(target.dataset.id);
      // 아이템 클릭시 액션 작성...
      console.log('선택된 아이템: ', itemId);
    }
  };

  return (
    <Wrapper onClick={onItemClick}>
      {items.map((item) => (
        <Item
          className="item"
          data-id={item.id} // data-id에 item.id 저장
          key={item.id}
          {...item}
          selected={selectedId === item.id}
          />
      ))}
    </Wrapper>
  )
}
  1. 아이템 요소에 data-* 속성 지정하기 : 부모 요소에서 클릭 이벤트를 적용할 때 클릭한 아이템을 알아내기 위한 식별자 역할
  • https://reactjs.org/docs/dom-elements.html
    리액트에서는 prop를 HTML 어트리뷰트가 아닌 DOM 프로퍼티로 표기하지기 때문에 prop에 camelCase를 사용하지만, data-와 aria- 속성은 예외적으로 snake-case로 작성한다.
  1. Element.closest()을 사용하여 .item을 선택자로 갖는 가장 가까운 요소 찾기
  • closet()은 제공된 선택자 문자열과 일치하는 노드를 찾을 때까지 및 요소의 상위 부모 요소들을 탐색한다. 일치하는 노드를 찾으면 자신 또는 일치하는 조상을 반환하고, 찾고자하는 노드가 없드면 null을 반환한다.

+ target vs currentTarget

target: 이벤트를 트리거한 요소 (사용자가 클릭한것!)
currentTarget: 이벤트 리스너가 붙어있는 요소


Refs

https://stackoverflow.com/questions/60288375/when-to-use-babel-config-js-and-babelrc

https://javascript.info/event-delegation

https://javascript.info/bubbling-and-capturing

profile
Web Frontend Developer 👩🏻‍💻 #React #Nextjs #ApolloClient

0개의 댓글