본문 바로가기
source-code/TypeScript

"'React'은(는) UMD 전역을 참조하지만 현재 파일은 모듈입니다" 에러 해결

by mattew4483 2023. 11. 18.
728x90
반응형

typescript로 React 애플리케이션을 작성하고 있는데

다음과 같은 타입 에러와 마주쳤다.

 

react component 내에 작성된 JSX 표현식에서 에러가 발생했는데...

해결 방안

해결 방법 자체는 단순하다.

아래의 두 해결책 중 하나를 사용하면 된다!

1. 해당 tsx 파일 내 React import

import React from "react";

React를 import 해주면 된다.

2. tsconfig compilerOptions 변경

{
  "compilerOptions": {
	// ...
    "jsx": "react-jsx", // react-jsx 또는 react-jsxdev로 설정
  }
}

tsconfig의 compilerOptions 중 jsx 속성을 변경해 주면 된다.

원인

그런데 영 찜찜하다.

위 두 방법으로 에러가 사라진 이유는 무엇일까?

아니 애초에, 왜 이런 타입 에러가 발생한 걸까?

→ typescript가 JSX 표현식을 어떻게 처리하는지 알 필요가 있겠다!

 

1. JSX

JSX는 Javascript의 확장 문법으로

XML 또는 HTML과 유사한 구문을 사용해 주로 React에서 UI 요소를 표한할 수 있도록 돕는다.

2. jsx in typescript

typescript는 JSX에 대한 타입 검사 및 Javascript로의 컴파일을 지원한다.

이를 위해 1) .tsx 확장자로 파일 이름 지정 2) jsx 옵션 활성화 가 필요한데...

 

확장자가 tsx가 아닐 경우

HTML 문법 자체에서 타입 에러가 발생하며 (당연하다. 그냥 TS 파일일 뿐이니!)

 

jsx 옵션을 활성화하지 않으면

JSX 문법을 사용할 수 없다는 에러가 발생한다.

3. jsx options

아하! TS가 JSX를 정상적으로 컴파일하기 위해서는 compilerOptions에서 jsx 플래그를 활성화해야 한다!

→ 활성화하는 건 좋은데, 어떤 모드로 활성화해야 하는 걸까?

모드 입력 출력 출력 파일 확장자
preserve <div /> <div /> .jsx
react <div /> React.createElement("div") .js
react-native <div /> <div /> .js
react-jsx <div /> _jsx("div", {}, void 0); .js
react-jsxdev <div /> _jsxDEV("div", {}, void 0, false, {...}, this); .js

tsc는 jsx에 다음과 같은 옵션들을 허용한다.

1. preserve

preserve 모드는 JSX를 출력 일부로 유지하여, 이를 다른 변환 단계(ex Babel)에서 추가로 사용한다.

(출력 파일 확장자는 .jsx)

 

2. react

react 모드는 React.createElement를 출력하며, 사용 전 JSX 변환을 거칠 필요가 없다.

(출력 파일 확장자는 .js)

 

3. react-native

react-native 모드는 모든 JSX를 유지한다는 점에서 preserv 모드와 유사하지만, 출력 파일 확장자가 .js!

 

4. react-jsx

react 17 버전부터 React.createElement를 사용하지 않고 JSX를 자동으로 변환하는데, 해당 버전을 위한 옵션.

(출력 파일 확장자는 .js)

 

react 17 버전부터는 React.createElement를 통해 Element 객체를 생성하는 것이 아니라,

jsx(개발 환경에서는 jsxDEV) 함수를 호출해 이를 생성해 주는데 → 해당 변경 사항을 반영했다고 이해할 수 있겠다!

 

5. react-jsxdev

react-jsx와 유사하게, react 17 업데이트에 따라 추가된 옵션(개발 환경)

4. React 참조

아하! 이제야 에러가 왜 발생했는지, 어떻게 해결했는지를 설명할 수 있다.

위 에러가 발생한 이유는?

1) tsconfig의 jsx 설정이 'react'로 되어있음

2) 해당 파일은 import React from 'react' 구문이 없음

3) tsc가 컴파일 시, 해당 JSX 구문은 React.createElement("...") 같은 형태로 출력됨

4) 하지만 해당 파일에는 React 가 선언되어있지 않기 때문에, 타입에러 발생

 

해결 방법은?

1) 해당 파일에서 React를 import 해, tsc가 JSX 구문을 컴파일할 때 React를 정상적으로 참조할 수 있도록 한다.

2) compilerOptions에서 jsx를 'react-jsx'로 설정해, 컴파일 시 React를 참조하지 않도록 한다.

번외) react-jsx

그런데... react-jsx, 즉 react17 버전부터는 React.createElement 대신

jsx라는 함수를 통해 Element 객체를 생성하므로, React를 import 하지 않아도 된다고 했다.

 

그렇다면, 이제 해당 파일에서는 jsx 함수를 import 해야 하는 게 아닌가?

import {jsx as _jsx} from 'react/jsx-runtime';

위 구문이 존재해야만

// react-jsx
_jsx("div", {}, void 0);

컴파일 시 출력될 때 참조 에러가 발생하지 않는 것 아닐까? (import React... 를 추가했던 이유와 동일하게..!)

 

→ 빌드 시점에 babel에서 해당 Import 구문을 inject 하기 때문에, 일일이 모든 파일에 작성해 줄 필요가 없다고 한다!


참고

https://velog.io/@jrl103/React%EB%8A%94-UMD-%EC%A0%84%EC%97%AD%EC%9D%84-%EC%B0%B8%EC%A1%B0%ED%95%98%EC%A7%80%EB%A7%8C-%ED%98%84%EC%9E%AC-%ED%8C%8C%EC%9D%BC%EC%9D%80-%EB%AA%A8%EB%93%88%EC%9E%85%EB%8B%88%EB%8B%A4

 

'React'는 UMD 전역을 참조하지만 현재 파일은 모듈입니다.

해결방법Create React App은 버전 4에서 즉시 사용 가능한 새로운 JSX 변환을 지원하지만 사용자 정의 설정을 사용하는 경우 작성 jsx하지 않고 TypeScript 오류를 제거하려면 필요하다.typescript버전 4.1 이

velog.io

https://www.typescriptlang.org/ko/docs/handbook/jsx.html#%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95

 

Documentation - JSX

Using JSX with TypeScript

www.typescriptlang.org

https://so-so.dev/react/import-react-from-react/

 

그 많던 import React from ‘react’는 어디로 갔을까

이 글에서는 React 17릴리즈에 포함되었던 JSX Transform의 RFC문서를 살펴보며 이 변경사항이 어떤 의미를 가지고 있는지 정리해 보았습니다. 중간중간 내용에 대한 첨언과 약간의 추측을 덧붙였습니

so-so.dev

 

728x90
반응형