JSX
는 자바스크립트를 확장한 문법으로, React에서는 UI를 어떻게 표현해야하는지를 설명하기 위해 React와 함께 사용할 것을 권장합니다.
JSX를 사용하면 자바스크립트 코드 내에서도 HTML 코드처럼 UI를 바로 표현할 수 있기 때문에 UI 관련 작업을 할 때 좀 더 직관적이고 용이한 개발이 가능하게 해줍니다.
function App() {
return (
<div>
<h1>Hello, World!</h1>
</div>
);
}
위 코드는 JSX 코드 예시입니다. 자바스크립트 문법도 HTML 문법도 아닌 걸 확인할 수 있습니다. JSX는 표준 자바스크립트 문법이 아니기 때문에, 웹 브라우저는 JSX 코드를 그대로 이해하지는 못합니다. 따라서 JSX 코드는 웹 브라우저에서 실행되기 전 Babel과 같은 도구를 사용하여 표준 자바스크립트 문법으로 변환되어야만 합니다.
"use strict";
function App() {
return React.createElement("div", null, React.createElement("h1", null, "Hello World!"));
위 코드는 Babel에 의해 표준 자바스크립트 문법(ES5)으로 변환된 JSX 코드입니다. JSX를 사용하면 위와 같이 복잡하고 중첩된 React.createElement() 호출 코드를 여러 번 작성할 필요가 없어지므로, UI 개발이 매우 편해지고 작성된 코드의 가독성도 높아집니다.
모듈(module)
이란 프로그램을 구성하는 구성 요소로, 관련된 데이터와 함수를 하나로 묶은 단위를 의미합니다.
애플리케이션의 기능이 많아질수록 작성해야 하는 코드의 양은 많아지고 복잡해집니다. 이때 모든 코드를 하나의 소스 파일에 작성하게 되면 코드의 가독성이 나빠질 뿐만 아니라 유지보수 또한 어려워집니다.
따라서 기능에 따라 관련된 데이터와 함수들을 별도의 모듈(module)로 나누어 관리하는 것이 보다 일반적이며, 이러한 방식을 모듈화 프로그래밍이라합니다. 모듈을 만들어 사용함으로써 기능에 따른 코드들을 체계적으로 관리할 수 있게 되며 유지보수도 쉬워집니다.
모듈화 프로그래밍을 통해 만들어진 웹 앱이 정상적으로 동작하기 위해서는 필요한 모듈들이 전부 네트워크를 통해 웹 브라우저에 전달되어야 합니다. 하지만 웹 브라우저에 전달되는 파일 단위의 모듈 개수가 늘어나게 되면 네트워크 자원의 낭비가 심해질 수 있습니다.
이러한 문제점을 해결하기 위해 웹 앱을 구성하는 수십, 수백 개의 리소스를 하나의 결과물로 만들어서 전송하는 방법이 사용되고 있으며, 이 과정에서 사용되는 도구가 바로 모듈 번들러(module bundler)
입니다.
모듈 번들러는 자바스크립트 파일 뿐만 아니라 이미지나 스타일시트 파일, 폰트 파일 등을 모두 하나의 모듈로 인식하고 이를 조합해서 병합함으로써 압축된 하나의 결과물(bundle)로 만들어 줍니다. 또한 최적화를 위해 하나의 파일을 여러 개의 파일로 분리하는 경우도 생길 수 있습니다.
대표적인 모듈 번들러로는 Browserify, Rollup, Parcel, Webpack 등이 있습니다. React에서는 편의성과 확장성이 좋은 Webpack을 주로 사용하고 있습니다.
Webpack
은 자바스크립트 애플리케이션을 위한 번들링과 컴파일을 결합한 정적 모듈 번들러입니다. Webpack에서는 자바스크립트 모듈 뿐만 아니라 웹 앱을 구성하는 모든 리소스(html, stylesheet, img, font 등)를 모듈로 취급합니다.
React에서 주로 Webpack을 번들러로 많이 사용하는 이유는 다음과 같습니다.
- 사용하지 않는 리소스의 제거와 같은 최적화 작업을 수행하여 웹 앱의 성능을 향상시킵니다.
- 번들링을 통해 웹 브라우저의 HTTP 요청 횟수의 제약을 피할 수 있도록 해줍니다.
- Webpack의 Code Splitting 기능을 사용하면, 웹 앱의 로딩 속도를 개선할 수 있습니다.
CRA(Create-react-App)을 사용하여 React 개발 환경을 설정하면 Webpack은 자동으로 설치됩니다.
Babel
은 일종의 자바스크립트 컴파일러로, 최신 자바스크립트 문법(ES6)이나 실험적인 자바스크립트 문법으로 작성된 코드를 이전 버전인 ES5 문법의 자바스크립트 코드로 변환해주는 툴 체인입니다.
다른 프로그래밍 언어와 달리 자바스크립트는 정말 다양한 종류와 버전의 웹브라우저에서 실행됩니다. 대부분의 최신 웹 브라우저에서는 최신 자바스크립트 문법을 바로 실행시킬 수 있지만, 구 버전의 웹 브라우저에서는 특정 코드가 실행되지 않을 수도 있고 특정 브라우저에서만 실행되지 않는 코드들도 있을 수 있습니다.
따라서 Babel과 같은 트랜스파일러를 사용하여 작성한 자바스크립트 코드가 어떤 환경에서도 정상적으로 동작할 수 있도록 이전 버전의 자바스크립트 문법으로 변환해 주는 것입니다.
React에서 사용하는 JSX 문법도 표준 자바스크립트 문법이 아니므로, Babel을 통해 ES5 문법의 자바스크립트 코드로 변환되어야만 웹 브라우저가 정상적으로 인식할 수 있습니다.
웹 브라우저에 내장된 HTML Parser는 HTML 문서의 구문을 분석하는 과정에서 HTML 표준에 맞지 않는 경미한 오류라면 자체적으로 보정하여 렌더링하기 때문에 큰 문제가 발생하지 않습니다.
하지만 XML 문서는 매우 규칙적이고 엄격합니다. JSX는 XML 구문에 자바스크립트 코드를 결합한 구문을 사용하기 때문에 JSX 구문을 작성할 때도 XML과 마찬가지로 XML 표준을 엄격하게 준수해야 합니다.
따라서 JSX 구문이 Babel을 통해 자바스크립트 구문으로 제대로 변환되기 위해서는 다음과 같은 규칙들을 반드시 준수해야 합니다.
HTML에서는 제대로 종료 태그를 사용하여 요소를 닫지 않아도 대부분 문제 없이 동작합니다. 하지만 JSX에서는 반드시 요소를 닫아야만 오류가 발생하지 않습니다.
만약 위의 코드처럼 "h1" 요소를 닫지 않고 JSX 코드를 저장하면, 실행중인 React 애플리케이션은 아래와 같은 오류를 발생시키며 동작을 멈출 것입니다.
컴포넌트가 여러 개의 요소를 한 번에 반환할 수 있도록 React에서는 반드시 컴포넌트의 최상위 요소가 하나만 존재하도록 강제하고 있습니다.
다음 코드에는 "h1"과 "p" 요소 이렇게 2개의 최상위 요소가 존재하므로, 오류가 발생합니다.
React v15 까지는 "div" 요소를 최상위 요소로 사용하여 나머지 요소들을 감싸주는 방식을 주로 사용했습니다. 하지만 이러한 방식은 단순히 JSX 문법을 맞추기 위해서 불필요한 "div" 요소를 추가해야만 하기에 권장하는 방법은 아닙니다.
React v16부터는 이러한 불필요한 "div" 요소의 사용을 재고할 수 있도록 Fragment라는 기능을 추가하였습니다. "fragment" 요소를 최상위 요소로 사용하면 별도의 요소를 추가하지 않고도 여러 자식 요소들을 그룹화 할 수 있습니다. 이러한 "fragment" 요소는 HTML 페이지에는 실제 렌더링되지 않기 때문에 최종 결과물에 불필요한 요소가 추가되지 않습니다.
만약 "fragment" 요소를 선언하는 것이 복잡하게 느껴진다면 아래 코드처럼 축약형 문법으로도 Fragment 기능을 사용할 수 있습니다.
JSX 구문에는 자바스크립트 표현식을 그대로 사용할 수 있습니다. 단, 자바스크립트 표현식을 사용할 때는 반드시 중괄호({})로 감싸줘야만 정상적으로 컴파일될 수 있습니다.
JSX 구문에는 중괄호({})로 감싸기만 하면 자바스크립트 주석도 그대로 사용할 수 있습니다. 다만, 주석을 작성할 때 일반 자바스크립트 코드보다는 좀 더 신경쓸 부분이 있습니다.
아래 코드처럼 주석을 작성하게 되면 오류가 발생합니다. 한 줄 주석에 사용되는 "//" 키워드는 자신의 오른쪽에 위치한 모든 코드를 주석으로 인식하기 때문에, JSX 구문에서 필수적인 오른쪽 중괄호(})를 찾지 못하기에 오류가 발생합니다.
따라서 다음 코드처럼 주석을 작성해야 합니다.
React에서는 모든 DOM 속성(attribute)을 카멜 표기법으로 표현합니다. 예를 들어, HTML 속성인 maxlength를 React에서는 maxLength로 표기해야 합니다. 예외적으로 aria-와 data-속성은 소문자로 표기하며 사용자 지정 속성도 소문자로만 표기합니다. 그리고 HTMl과는 다르게 표기해야 올바르게 동작하는 몇몇 DOM 속성도 존재합니다.
HTML 요소에 CSS 클래스를 사용하기 위해 HTML에서는 아래 코드와 같이 class라는 속성을 사용하면 됩니다.
<div class="container"></div>
하지만 JSX에서는 class 대신 className이라는 속성을 사용해야 합니다. class라는 단어가 자바스크립트 문법에서 클래스(class)를 생성하기 위한 키워드로 이미 예약되어 있기 때문에 중복을 피하기 위해 className을 사용해야 합니다.
<div className="container"></div>
React v15까지는 className을 사용하는 대신 실수로 class를 잘못 사용하게 되면 오류가 발생했었습니다. 하지만 React v16부터는 JSX 코드에 잘못 사용된 class 속성을 자동으로 className으로 변환해 줍니다. 그러나 의미 상의 혼동을 방지하기 위해서라도 JSX라는 className 속성을 사용하는 것이 바람직합니다.
HTML의 for 속성도 자바스크립트에서 반복문을 정의하는 for 키워드와 중복되므로 JSX에서는 htmlFor 속성으로 바꿔 사용해야 합니다.
React v16부터는 모든 표준 HTML DOM 속성들과 사용자 정의 DOM 속성들을 완벽하게 지원합니다.
또한 SVG 속성들도 완벽하게 지원합니다.