Skip to main content
입문

변환과 번들링: TypeScript와 JSX는 어떻게 실행 가능한 파일이 되는가

TypeScript와 JSX가 실행 대상 코드로 바뀌는 과정과 여러 파일의 관계가 전달할 결과로 표현되는 과정을 분리해 이해하고, 빌드 실패가 생긴 단계를 판단한다.

마지막 검증 재검증 정책: 제품 버전 의존: 새 주요 버전마다 재검증
목차
표준·구현·측정·해석 표시는 무엇인가요?
  • 표준웹 표준이나 언어 명세가 정한 동작
  • 구현특정 기술이나 브라우저가 실제로 구현한 동작
  • 측정명시한 환경에서 직접 실행해 관찰한 결과
  • 해석앞선 근거에서 도출한 설계 판단
  • 미확인아직 공식 근거나 재현 결과를 확인하지 못한 내용

30초 요약

이 글에서 기억할 것은 네 문장이다.

  1. 변환은 코드의 표현을 바꾸고, 번들링은 파일 사이 관계를 전달할 출력으로 만든다.
  2. TypeScript 타입은 결과 JavaScript에서 사라지고, JSX의 처리 결과는 변환 설정에 따라 달라진다.
  3. 번들링하더라도 출력은 하나 또는 여러 파일일 수 있고, 개발 중에는 파일별로 제공할 수도 있다.
  4. 실패하면 대상 찾기, 표현 바꾸기, 출력 조립 중 어디서 멈췄는지 먼저 나눈다.

변환과 번들링은 책임이 다르다

축소해서 보면 흐름은 다음과 같다.

원본 코드 + 대상 설정 ── 표현 바꾸기 ──> 대상 코드
해석된 파일 + 파일 사이 관계 + 출력 설정 ── 조립 ──> 전달할 결과

실제 도구가 반드시 이 순서로 한 줄씩 실행된다는 뜻은 아니다. 무엇을 바꾸는 책임과 무엇을 묶는 책임을 구분하기 위한 사고 도구다.

책임주로 받는 입력주로 만드는 출력대표 실패
변환원본 코드, 대상과 변환 설정대상 코드나 다음 단계가 읽을 표현지원하지 않는 문법, 잘못된 변환 옵션
번들링해석·변환된 파일, 파일 사이 관계, 출력 설정하나 이상의 전달 파일시작 파일·출력 경로·자산 연결 오류

다음 코드는 작성하기에는 편하지만 실행 대상이 그대로 이해하지 못할 수 있다.

const title: string = "안녕하세요"
const view = <h1>{title}</h1>

“더 새 문법을 더 오래된 문법으로 바꾸는 일”을 트랜스파일(transpile)이라고도 부른다. 이 글에서는 별도 단계처럼 외우지 않고 변환의 한 종류로 다룬다.

변환의 대표 사례

타입스크립트의 타입은 출력에서 사라진다

원본은 타입 정보를 포함한다.

type User = { name: string }
 
const user: User = { name: "민지" }
console.log(user.name)

TypeScript 5.9.3으로 이 글의 예제를 ES2022(출력에서 사용하는 JavaScript 문법 수준) 코드로 바꾸면 핵심 출력은 다음과 같다.

const user = { name: "민지" }
console.log(user.name)

여기서 실무 경계가 하나 생긴다. 서버 응답이 실제로 { name: 42 }를 보내도 타입 선언만으로 실행 중인 값이 거부되지는 않는다.

외부 입력의 실제 모양을 보장하려면 서버 응답 경계에서 스키마 검사(실제 값의 모양을 실행 중 확인하는 검사) 같은 절차가 별도로 필요하다.

JSX는 렌더링 전에 변환 단계에서 처리된다

React 코드의 JSX는 HTML 문자열이 아니다.

const greeting = <h1 className="title">안녕하세요</h1>

TypeScript의 react-jsx 설정에서 이 글의 예제를 바꾸면 다음과 같은 호출이 만들어진다. 아래 코드는 실제 출력의 핵심 구조를 유지하면서 읽기 좋게 공백과 문자열 표기만 정리했다.

import { jsx as _jsx } from "react/jsx-runtime"
 
const greeting = _jsx("h1", {
  className: "title",
  children: "안녕하세요",
})

_jsx 같은 보조 함수(helper)는 변환기가 만든 출력에서 React 엘리먼트 설명을 만드는 함수다. 이 엘리먼트를 만드는 순간 컴포넌트가 렌더링되거나 브라우저가 문서를 표현하는 객체 구조인 DOM(Document Object Model)이 생기는 것은 아니다. TypeScript가 JSX를 남긴 설정에서도 JavaScript 실행환경이 직접 JSX를 읽는다는 뜻은 아니다. 뒤의 변환 단계가 처리해야 한다. 따라서 JSX 변환React 렌더링은 서로 다른 시점의 작업이다.

번들링은 여러 코드의 관계를 출력으로 표현한다

앞선 두 글에서 도구는 시작 파일부터 필요한 코드를 찾고 각 지정자를 실제 대상으로 연결했다.

이제 다음 관계가 준비되었다고 하자.

main.js ──> greeting.js ──> react

이 연결들을 실행환경에 전달할 파일로 표현하는 결과가 필요하다.

여기서 “번들”을 항상 “애플리케이션 전체가 든 JavaScript 한 파일”로 외우면 안 된다. 설정과 로딩 경계(코드를 언제 별도 파일로 불러올지 나눈 지점)에 따라 결과가 여러 파일일 수 있다. 어떤 코드를 어느 파일로 나누는지는 다음 글인 코드 분할과 트리 셰이킹에서 다룬다.

번들링은 JavaScript 실행의 필수 조건이 아니다

따라서 다음 두 문장을 분리해야 한다.

  • 변환이 필요한가? 대상이 원본 문법이나 형식을 이해하는지 묻는다.
  • 묶어서 전달할 것인가? 요청 수, 로딩 경계와 운영 최적화 목표를 묻는다.

개발 서버에서 파일을 따로 제공한다고 해서 변환까지 하지 않는 것은 아니다. 반대로 이미 실행 가능한 JavaScript도 전달 방식을 최적화하기 위해 묶을 수 있다.

산출물은 빌드가 만든 결과다

산출물에는 JavaScript만 있는 것이 아니다. 스타일 파일, 이미지, 파일 이름과 파일 사이의 참조 정보가 함께 나올 수 있다. 원본과 다르게 보이는 이름이나 코드가 있어도 곧바로 오류는 아니다. 대상과 출력 규칙에 맞춘 결과일 수 있다.

분석 보고서나 중간 결과처럼 직접 배포하지 않는 산출물도 있다. 검증을 통과하고 배포 대상으로 선택한 산출물만 사용자에게 전달할 후보가 된다.

다만 문법 변환과 실행 기능 보충도 구분해야 한다.

그래서 빌드 대상을 정할 때는 “문법을 읽을 수 있는가”와 “사용한 기능이 존재하는가”를 각각 확인한다.

React Native에서는 세 책임을 나누어 본다

해석:      이 요청은 어느 파일인가?
변환:      이 파일을 대상이 읽을 수 있는가?
직렬화:    변환된 결과를 어떤 출력으로 조립할까?

이 구분은 React Native 빌드가 실패했을 때 특히 유용하다. 같은 “Metro 오류”여도 플랫폼 파일을 찾지 못한 경우와 TypeScript에서 JSX를 쓴 TSX 문법을 바꾸지 못한 경우, 최종 출력 생성에 실패한 경우는 확인할 입력이 다르다. 세 이름을 실제 시간 순서라고 외우기보다 책임의 경계로 사용한다.

오류는 실패한 책임의 입력부터 본다

보이는 증상먼저 분류할 단계먼저 확인할 입력
경로나 대상을 찾지 못함해석지정자, 가져온 파일, 별칭, 플랫폼
특정 .ts·.tsx 문법에서 멈춤변환원본 문법, 파일 확장자, 변환기와 옵션
타입 오류가 배포 전 검사에서 발생타입 검사tsconfig, 검사 명령, 전체 타입 관계
출력 파일 생성이나 참조 연결 실패번들링·직렬화시작 파일, 출력 설정, 자산 처리 규칙
오래된 대상에서 실행 기능이 없음호환성대상 범위, 기능 지원, 폴리필 설정

캐시 삭제는 올바른 입력과 설정인데 이전 결과가 재사용된다는 근거가 있을 때 조사한다. 단계를 나누지 않은 채 먼저 캐시를 지우면 원인을 재현할 단서도 함께 사라질 수 있다.

이 글의 경계

이번 글은 원본 코드가 대상 코드와 전달 결과로 바뀌는 책임을 구분했다. 다음 내용은 분리한다.

  • 어떤 코드를 별도 파일로 나누고 사용하지 않는 코드를 제외하는가: 다음 글의 주제
  • 변환된 위치를 원본 파일의 줄과 열로 되돌리는가: 소스 맵
  • 같은 입력에서 같은 결과를 다시 만드는가: 재현 가능한 빌드
  • 검증한 결과를 어느 환경과 사용자에게 전달하는가: 지속적 통합·전달(CI/CD)과 배포

다음 글에서는 그래프와 변환 결과를 바탕으로 코드 분할과 트리 셰이킹이 어떤 조건에서 가능한지 살펴본다.

Active recall

기억에서 꺼내 보기

답을 쓰지 않아도 됩니다. 먼저 머릿속으로 답한 뒤 펼쳐서 정답·이유·흔한 오해를 비교하세요.

  1. 01변환과 번들링은 무엇이 다른가?

    정답

    변환은 코드의 표현을 대상이 읽을 형태로 바꾸고, 번들링은 해석된 파일 사이 관계를 하나 이상의 전달 파일로 표현한다.

    왜 그런가

    한 빌드 명령이 두 작업을 함께 해도 표현을 바꾸는 책임과 여러 입력의 관계를 출력하는 책임은 구분된다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

  2. 02TypeScript가 JavaScript로 변환되면 타입 검사가 런타임에도 남을까?

    정답

    아니다. 타입 표기는 출력 JavaScript에서 지워지므로 외부 데이터는 런타임에서 별도로 검증해야 한다.

    왜 그런가

    정적 타입 검사는 실행 전 오류를 찾는 책임이고, 변환된 코드가 받은 실제 서버 값의 형태를 검사하는 책임은 아니다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

  3. 03실행환경이 JSX 태그를 그대로 읽어 React 화면을 만드는가?

    정답

    직접 읽지 않는다. 실행 전에 설정된 변환 단계가 JSX를 처리하며, TypeScript가 호출로 바꿀지 다음 단계에 남길지는 jsx 옵션에 따라 달라진다.

    왜 그런가

    JSX 변환과 React 렌더링은 다른 시점의 작업이며 정확한 출력 보조 함수와 변환 담당 도구는 설정에 따라 달라진다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

  4. 04빌드가 실패했을 때 가장 먼저 무엇을 구분할까?

    정답

    대상을 찾지 못한 해석 실패인지, 코드 표현을 대상 형태로 바꾸지 못한 변환 실패인지, 전체 출력을 만들지 못한 조립 실패인지 구분한다.

    왜 그런가

    실패 단계가 달라지면 확인할 입력도 경로·설정, 원본 문법·변환 옵션, 시작 파일·출력 설정으로 달라진다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

출처와 검증 범위

아래 날짜는 링크를 마지막으로 열어 본 날입니다. 문서 상단의 검증일은 글의 설명과 적용 범위를 다시 확인한 날입니다.

  1. TypeScript for the New Programmer — Erased TypesTypeScript · 공식 문서 · 확인 2026-08-04
  2. TSConfig Reference — jsxTypeScript · 공식 문서 · 확인 2026-08-04
  3. Writing Markup with JSXReact · 공식 문서 · 확인 2026-08-04
  4. createElementReact · 공식 문서 · 확인 2026-08-04
  5. Loaderswebpack · 공식 문서 · 확인 2026-08-04
  6. Conceptswebpack · 공식 문서 · 확인 2026-08-04
  7. Features — TypeScriptVite · 공식 문서 · 확인 2026-08-04
  8. Building for ProductionVite · 공식 문서 · 확인 2026-08-04
  9. Why ViteVite · 공식 문서 · 확인 2026-08-04
  10. ConceptsMetro · 공식 문서 · 확인 2026-08-04
이 문서의 마지막까지 읽었습니다.