Skip to content

Instantly share code, notes, and snippets.

@bang9
Created February 21, 2024 04:00
Show Gist options
  • Save bang9/cd03e74ec9b49687aec071b3dc7247c7 to your computer and use it in GitHub Desktop.
Save bang9/cd03e74ec9b49687aec071b3dc7247c7 to your computer and use it in GitHub Desktop.
Jest unexpected token error

원인

JS 환경에서 많이 사용되는 테스트 도구인 Jest 를 사용하다 보면 한번씩 만나게되는 에러가 SyntaxError: Unexpected token 'export' 같은 에러이다.

이는 기본적으로 Jest 가 CJS 모듈 시스템에서 돌아가기 때문이다.

CJS 모듈 시스템에서는 require, module.exports 키워드를 사용한다. 테스트를 실행하기 위해서 ESM 모듈을 만나게 되고 import, export 키워드를 만나게 되면 해석을 할 수 없게되면서 에러가 발생한다.

"어? 하지만 내 코드에서는 import 를 잘 사용하고 있는데요?" 라는 의문이 생길수도 있다. 이는 기본적으로 Jest 가 소스코드를 babel 을 통해서 transform 한 뒤에 실행을 시켜주기 때문인데, 일반적으로 프로젝트 내의 테스트 코드가 실행되는 스코프에서 참조 가능한 파일들은 이 변환을 거치게 된다.

문제는 바로 ESM 만 지원하는 특정 모듈을 사용할 때 문제가 발생한다. Jest 기본값에 의해서 node_modules 내에 존재하는 모듈들은 transform 을 거치지 않기 때문이다. jest-config

이때문에 node_modules 에 포함된 ESM 만 지원하는 모듈을 테스트에서 사용하는 경우 위의 에러를 만나게 된다.

해결 방법

이제 문제의 원인을 알았으니 우리에게는 몇가지 선택지가 주어진다.

  1. CJS 모듈이 지원되는 버전이 있다면 다운그레이드 한다.
  2. ESM 환경에서 Jest 를 사용한다.
  3. ESM 모듈을 transform 해준다.

1번의 경우 대부분 최신 스펙인 ESM 모듈을 지원하는 버전이 높을것이다. CJS 패키지가 따로 있고 정식 지원을 해주는게 아닌 이상 추천하지 않는다.

2번의 경우 Jest 자체에서 ESM 환경 지원은 experimental 이라고 못박고 있다. 환경을 다시 설정하면서 마주할 문제들이 아마 더 크고 고통스러운 문제가 될 수도 있다.

3번이 가장 간단하다. transformIgnorePatterns 을 사용해서, 특정 모듈을 transform 제외 목록에 포함시키지 않도록 하는것이다.

const config = {
  transformIgnorePatterns: ['/node_modules/(?!(foo|bar)/)'],
};

module.exports = config;

부정의 부정이라서 다소 이해하기가 어렵지만, 위와 같이 설정할 경우 /node_modules/foo, /node_modules/bar 경로에 속하는 파일들은 transform ignore 하지 말라는 뜻이다.

즉, 해당 경로에 속하는 파일들은 transform 타겟으로 잡히게 되고, 정상적으로 변환되어 테스트가 실행된다.

@liamcho
Copy link

liamcho commented Feb 22, 2024

Thank you for sharing this. It is very helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment