들어가기
예전부터 React로 개발하면 맨 윗줄에 import React from 'react'를 쓰는 게 거의 관행이었다.
뭔가 왜? 라는 의문을 가질 것도 없이 그렇게 해야 React를 쓸 수 있다고 이해했기 때문이었고, 단축키인 rafce를 사용하면 알아서 import React from 'react'가 포함된 화살표 함수 컴포넌트를 만들어주기 때문에 크게 불편함을 느끼지 못하고 있었다.
그런데 어느 순간부터 import React from 'react'에 밑줄이 쳐지면서 아래와 같은 메세지가 생겼다.
이게 불편하다는 걸 인지하게 된 첫 번째 이유는 "안 쓰고 있는데... 왜 이걸 import 해야 하지?" 라는 의문이었다.
두 번째로는 저걸 지우지 않은 상태로 Vercel을 사용해 빌드를 했더니 에러 메세지가 막 뜨는 것이었다...
아니 이거 없으면 문제 생기는 거 아니었어? 안 쓰고 있기만 해도 이렇게 문제 생기는 거야? 하고 당황스러웠다.
아마 뭔가 빌드 설정을 엄격하게 해서 그런 걸지도 모르고, 이 부분은 내 기억이 정확하지 않을 수 있지만,
어쨌든 그래서 일일이 여러 개의 화살표 컴포넌트에서 import React from 'react'를 지우다 보니 매우 귀찮다는 걸 느꼈다.
이거 rafce할 때 import 어쩌고만 안 나오게 할 순 없나?
그리고 쟤 왜 갑자기 없어도 잘만 돌아가는 거야?
라는 의문에서 이번 글을 시작하게 되었다! 🎉
import React from 'react'가 있었는데요? 없었습니다...
먼저 공식 문서를 확인해보자.
react.dev가 아니라 legacy 버전에만 있지만 내가 깨달은 것 자체가 legacy이기 때문에...^^
무려 2020년, React 17 이후에 바뀐 것인데 왜 나는 이상함을 느끼지 못했을까?
브라우저는 JSX를 기본적으로 이해하지 못해서 대부분 React 사용자는 Babel 같은 트랜스파일러나 TS 같은 슈퍼셋 언어로 JSX 코드를 일반 JS로 변환한다. CRA나 NextJS 같은 툴도 내부에 JSX 트랜스폼을 포함하고 있다.
React 17 릴리즈와 함께 JSX 트랜스폼을 개선하고자 했지만 기존 설정을 깨고 싶진 않았기에 Babel과 협력해 새로운 JSX 트랜스폼 버전을 제공했다.
이는 3가지 장점이 있었는데, 먼저 새 트랜스폼을 사용하면 React를 import하지 않고도 JSX를 쓸 수 있고 번들 사이즈를 조금 개선할 수 있으며, 향후 React를 배우는데 필요한 몇 가지 개념을 줄일 수 있도록 개선될 여지가 있었다.
그냥 핵심은 React 17 릴리즈 되면서 새 트랜스폼 만들었는데 React import 안해도 JSX 쓸 수 있게 했어! 인 것이다.
근데 이제 기존 설정을 건드린 건 아니라 필수는 아니고 네가 원하면 게속 써도 돼 :) 라고 합니다.
그럼 이전 트랜스폼이랑 React 17의 트랜스폼은 뭐가 어떻게 달라졌는지 알아보자.
이전 트랜스폼과 React 17의 트랜스폼
JSX를 사용하면 컴파일러가 브라우저에서 이해할 수 있는 React 함수 호출로 변환 시켜준다.
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
이런 코드가 있을 때 이전 트랜스폼은 아래와 같이 변환 시켰다.
import React from 'react';
function App() {
return React.createElement('h1', null, 'Hello world');
}
맞다. React.createElement~ 로 시작하기 때문에 React가 import 되어야만 했다.
이런 방식은 성능이나 기술 부채 등에 많은 제약이 있다고 한다. (RFC문서 참고)
(정확히 어떤 성능, 기술 부채에 제약이 있었고 이렇게 변환한 것이 React를 배우는데 필요한 개념을 줄여주는지도 알아보자.)
React 17 부터는 아래와 같이 JSX를 react/jsx-runtime의 jsx 함수로 변환하는 방식으로 진행된다.
// Inserted by a compiler (don't import it yourself!)
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Hello world' });
}
컴파일러에 의해 import 구문이 insert되기 때문에 개발자가 직접 import할 필요가 없어진다.
물론 useState나 useRef같이 React에서 제공하는 hook 같은 걸 쓰려면 React를 import 해야 한다.
적용하기
공식 문서에 어떻게 적용해야 하는지 매우 자세히 안내되어 있다.
나의 경우 VSC의 Setting에 'import React from 'react''를 검색하고 스니펫 설정을 바꿔줬다.
이 부분을 해제해주고 ESLint에도 걸리지 않게 공식 문서에서 알려준 코드 2줄을 추가했다.
rules: {
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'react/react-in-jsx-scope': 'off', // 1번
'react/jsx-uses-react': 'off', // 2번
},
이제 rafce로 화살표 함수 컴포넌트를 만들어도 import React from 'react'가 나오지 않는다. :)
참고
'⚛️ React' 카테고리의 다른 글
[React] useState 훅과 용례 (1) | 2024.09.24 |
---|---|
[React] useMemo와 useCallback (0) | 2024.09.23 |
[React] React의 렌더링 방식과 웹 브라우저의 동작 (0) | 2024.03.28 |
[React] Vite의 환경 변수 (cf. CRA) (0) | 2024.02.16 |
[React] useState (0) | 2024.02.03 |