JavaScript 테스트 라이브러리 만들기 (3부)

SanE·2025년 11월 24일
post-thumbnail

🤔 들어가며

이전 포스트를 통해 로직 구현을 완료했다.
이번에는 npm에 배포하는 과정과 테스트 라이브러리를 구현하며 느낀점에 대해 작성하려고 한다.

테스트 라이브러리 구현에 관한 자세한 내용은 이전 포스트를 참고해주세요.

💡 npm에 배포하기

앞서 완성된 라이브러리를 npm에 배포해보자.

하지만 그 전에 로컬에서 먼저 테스트해보는 것이 좋을 것이다.

📋 npm link로 로컬 테스트하기

npm에 배포하기 전에 npm link를 사용하면 로컬에서 패키지를 테스트할 수 있다.

1단계: 패키지에서 링크 생성

개발 중인 js-te 디렉토리에서 실행한다.

npm link

참고 : 변경 사항이 있을 때 unlink → link를 할 필요 없이 link만 하면 된다.

2단계: 테스트 프로젝트에서 링크 연결

테스트할 프로젝트 디렉토리로 이동해서 실행한다.

npm link @dannysir/js-te

3단계: 테스트 실행

이제 실제 npm 패키지처럼 사용할 수 있다.

{
  "type": "module",
  "scripts": {
    "test": "js-te"
  }
}
npm test

4단계: 테스트 완료 후 링크 해제

테스트가 끝나면 링크를 해제한다.

# 테스트 프로젝트에서
npm unlink @dannysir/js-te

# js-te 디렉토리에서
npm unlink -g

📋 Scoped Package로 배포

로컬 테스트가 완료되었다면 이제 npm에 배포한다.

앞서 프로젝트 세팅 단계에서 언급했듯이, js-te라는 이름은 이미 npm에 유사한 이름이 존재해서 배포가 불가능했다.

따라서 Scoped Package 형태로 배포한다.

{
  "name": "@dannysir/js-te",
  "version": "0.1.0"
}

배포 전 체크리스트

  • 로컬 테스트 완료
  • README.md 작성
  • package.json의 version, description, keywords 확인
  • .npmignore 설정 (불필요한 파일 제외)
  • npm 로그인 상태 확인 (npm whoami)

배포 명령어

npm publish --access public

--access public 플래그가 필요한 이유는 scoped package의 기본 설정이 private이기 때문이다.

📋 버전 관리

버전 구조: MAJOR.MINOR.PATCH

# 패치 버전 업데이트 (0.1.0 → 0.1.1)
# 버그 수정, 내부 리팩토링
npm version patch

# 마이너 버전 업데이트 (0.1.0 → 0.2.0)
# 하위 호환성 유지하며 기능 추가
npm version minor

# 메이저 버전 업데이트 (0.1.0 → 1.0.0)
# 하위 호환성 깨지는 변경
npm version major

각 버전의 의미

  • PATCH (0.1.0 → 0.1.1)
    • 버그 수정
    • 성능 개선
    • 문서 수정
    • 기존 API에 영향 없음
  • MINOR (0.1.0 → 0.2.0)
    • 새로운 기능 추가
    • 기존 기능은 그대로 동작
    • 하위 호환성 유지
  • MAJOR (0.1.0 → 1.0.0)
    • API 변경으로 기존 코드가 작동 안 함
    • 함수 시그니처 변경
    • 기능 제거

버전 업데이트 및 재배포

# 1. 버전 업데이트 (자동으로 git commit & tag 생성)
npm version patch

# 2. 재배포
npm publish

npm version 명령어는 다음 작업을 자동으로 수행한다:

  • package.json의 version 필드 업데이트
  • git commit 생성 (메시지: "v0.1.1")
  • git tag 생성 ("v0.1.1")

📋 배포 후 사용하기

이제 사용자는 다음과 같이 라이브러리를 설치할 수 있다.

npm install --save-dev @dannysir/js-te

설치전 npm view 명령어로 배포 상태를 확인할 수 있다.

package.json 설정

{
  "type": "module",
  "scripts": {
    "test": "js-te"
  }
}

테스트 작성

// math.test.js
describe('Math', () => {
  test('addition works', () => {
    expect(1 + 1).toBe(2);
  });
});

실행

npm test

👍  개선할 점

📋 ESM & Common JS

현재 라이브러리는 ESM을 기본으로 하고 있다.

CommonJS도 지원하기 위해서는 CommonJS에 대응하는 파일을 따로 생성해야 한다.

그러나 현실적으로 매번 수정할 때마다 2개의 파일을 수정해야 하는 문제가 있다.

따라서 이를 위해 Rollup과 같은 번들러를 이용해 하나의 소스에서 ESM과 CommonJS 두 가지 형태로 빌드하여 배포하는 방법이 있다.

📋 mocking 기능의 문제점

현재 mock을 선언한 후에 반드시 동적 import(await import())를 해야 하는 제약이 있다.

ESM의 정적 import는 파일 실행 시점에 최상단에서 먼저 실행되기 때문에, mock 등록보다 먼저 모듈이 로드되어 mock이 적용되지 않는다.

CommonJS의 경우 require.cache를 통해 이미 로드된 모듈의 캐시를 제거하고 다시 로드할 수 있어, 정적 require 후에도 mock을 적용할 수 있는 방법이 존재한다.

따라서 향후 사용성 개선을 위해 CommonJS 지원을 고려해볼 필요가 있다.

😁 느낀점

라이브러리를 직접 만들고 배포해보며 가장 크게 고민했던 부분은 다음과 같았다.

"어떻게 해야 다양한 사용자 환경에 모두 대응할 수 있을까?"

📋 범용성의 어려움

단순해 보이는 기능 하나에도 수많은 경우의 수가 존재한다.

  • 어떤 사용자는 절대 경로를 사용하고
  • 어떤 사용자는 상대 경로를 사용하고
  • 어떤 프로젝트는 ESM을 쓰고
  • 어떤 프로젝트는 CommonJS를 쓴다

이런 모든 환경을 지원하는 라이브러리를 만드는 것은 생각보다 훨씬 복잡한 일이었다.

예를 들어 단순히 "절대 경로와 상대 경로를 모두 지원하자"는 요구사항 하나를 위해

  • Babel 플러그인을 직접 구현하고
  • AST를 파싱하고 변환하고
  • 경로를 정규화하는 복잡한 로직을 추가해야 했다

📋 새삼 대단하게 느껴지는 Jest

이 과정을 겪으며 Jest가 얼마나 잘 만든 라이브러리인지 새삼 느꼈다.

Jest는 사용자가

  • import 없이 test, expect를 쓸 수 있고
  • 아무 경로나 사용해도 mocking이 되고
  • 복잡한 설정 없이도 바로 동작한다

이런 "당연해 보이는" 사용성 뒤에는 엄청난 양의 엣지 케이스 처리와 최적화가 숨어있다는 것을 알게 되었다.

우리가 평소에 아무 생각 없이 사용하는 라이브러리들은 이런 문제들을 위해 얼마나 많은 노력이 들어갔을지 감조차 잡히지 않는다.

📋 작지만 의미 있는 경험

물론 현재 구현한 js-te는 Jest에 비하면 정말 작고 단순한 라이브러리다.

하지만 직접 만들어보며

  • npm 패키지 구조와 배포 과정
  • CLI 도구 제작 방법
  • Babel을 활용한 코드 변환
  • 모듈 시스템의 차이(ESM vs CommonJS)
  • 경로 처리의 복잡성

이런 것들을 몸소 체험할 수 있었다.

특히 "왜 Jest는 import 없이 사용할 수 있지?", "모킹은 어떻게 구현하지?" 같은 궁금증을 직접 해결해보는 과정이 정말 값진 경험이었다.

📎 프로젝트 링크

profile
JavaScript를 사용하는 모두를 위해...

5개의 댓글

comment-user-thumbnail
2025년 11월 25일

글을 읽으면서 정말 많은 인사이트를 얻었습니다. 단순히 테스트 라이브러리를 만든 수준이 아니라, npm 배포 → ESM/CJS 호환성 → Babel 기반 mocking → 경로 처리 → CLI 흐름까지 직접 부딪혀보신 게 정말 인상적이네요.

특히 mocking 제약이나 ESM/CJS 양쪽을 고려해야 하는 지점은 실제로 만들어보지 않으면 절대 체감할 수 없는 부분인데, 이를 직접 해결해보셨다는 점에서 엄청난 경험치를 쌓으신 것 같습니다.

배포 과정도 차근차근 정리되어 있어서 저 같은 사람에게도 큰 도움이 됐어요. 링크 걸어두신 GitHub와 npm 패키지도 구경해봤는데, 이름만큼이나 구조도 깔끔하더라고요!

패키지를 사용만 해봤지, 실제로 만들어볼 생각은 못했었는데, 이후에 저도 시도해봐야겠네요! 기회가 된다면 이런 주제로 서로 경험 나누면서 네트워킹할 수 있으면 좋겠습니다. 앞으로도 계속 응원할게요!

1개의 답글
comment-user-thumbnail
2025년 11월 25일

이번 코스가 끝나고 테스트 라이브러리 작성법에 대한 공부를 하려고 디스코드 채널에서 찾아보던 중, 정말 많은 도움이 된 시리즈네요 :)

velog와 깃허브 가독성이 너무 좋아서 저같은 초보자도 읽기 쉬웠고, 좋은 공부가 되었어요!
나중에 테스트 라이브러리 코딩할 때 큰 도움이 될 것 같습니다. 좋은 글 감사합니다!

1개의 답글