JSX 표기법
리액트는 JSX 표기법을 사용한다. JSX는 영어로 다음과 같은 의미를 갖고 있다.
A syntax extension jo JavaScript.
문장을 그대로 해석해 보면 자바스크립트의 확장 문법이라는 뜻이다.
그럼 문법을 어떻게 확장한 것일까? JSX는 JavaSciprt와 XML/HTML을 합친 것이라고 보면 된다. JSX의 X는 extension의 X로 볼 수도 있지만 실제로는 JavaScript and XML의 앞 글자를 따서 JSX라고 부르는 것이다.
먼저 리액트 프로젝트를 만든 뒤 src 폴더 안에 있는 파일을 모두 삭제하고, index.js를 새로 만든다.
index.js에 리액트 기반을 작성하면서 JSX에 관해 알아보자.
먼저 react-dom 라이브러리에서 ReactDom이라는 이름으로 모듈을 import 한다.
🔽 ReactDom import
import ReactDOM from "react-dom";
다음으로 App이라는 이름으로 화살표 함수를 이용해 함수를 준비한다. 우선 null을 반환하는 함수로 정의한다.
🔽 App 함수 정의
const App = () => {
return null;
};
ReactDom은 render라는 함수를 제공한다. 첫 번째 인수에 'render 대상', 두 번째 인수에 'render 위치'를 지정한다.
🔽 인수 지정
ReactDOM.render(<App />, document.getElementById("root"));
첫 번째 인수가 <App />으로 지정되어 있다. 리액트에서는 함수명을 HTML과 같이 태그로 감싸서 컴포넌트로 다룰 수 있다.
두 번째 인수는 root라는 id를 지정했다. 이것은 public > index.html에 있는 div 태그를 가리킨다.
🔽 지정된 div 태그
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
(...생략)
</head>
<body>
(...생략)
<div id="root"></div>
</body>
</html>
SPA에서 HTML 파일은 한 개뿐이므로 예제와 같이 애플리케이션 루트에 'HTML 중 여기에 컴포넌트를 렌더링 하라'고 지정한다. 지금은 App 함수가 null을 반환할 뿐이므로 화면은 하얗게 보일 것이다.
SPA(Single Page Application)에서는 기본적으로 HTML 파일은 하나만 사용하고 자바스크립트를 이용해 화면을 전환함으로써 화면 이동 등의 동작을 표현한다.
🔽 h1 태그로 문자 표시
import ReactDOM from "react-dom";
const App = () => {
return <h1>Hello!</h1>;
};
ReactDOM.render(<App />, document.getElementById("root"));
다음과 같이 표시된다. 이렇게 JSX 표기법에서는 함수의 반환값으로 HTML 태그를 기술할 수 있고 그것을 컴포넌트로 다뤄 화면을 구성한다.
JSX 규칙
- retrun 이후 행이 여럿일 때는 ( )로 감싼다.
- return 이후
자바스크립트 코드를 쓸 때는{ }를 사용한다. return 이후는 태그 한 개로 감싼다.- 태그를 열었으면 꼭 닫아야 한다.
🔽 div 태그로 감싸기
import ReactDOM from "react-dom";
const App = () => {
return (
<div>
<h1>Hello!</h1>
<p>안녕하세요!</p>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
리액트에서 제공하는 Fragment를 사용할 수도 있다.
🔽 Fragment 사용
import ReactDOM from "react-dom";
import { Fragment } from "react";
const App = () => {
return (
<Fragment>
<h1>Hello!</h1>
<p>안녕하세요!</p>
</Fragment>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
🔽 빈 태그 사용
import ReactDOM from "react-dom";
const App = () => {
return (
<>
<h1>Hello!</h1>
<p>안녕하세요!</p>
</>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
div 태그와 달리 이 표기법들은 불필요한 DOM을 생성하지 않는다. 따라서 에러를 피하기 위해 바깥쪽을 감싸고 싶은 경우 등에 효과적으로 사용할 수 있다.
컴포넌트 사용 방법
지금까지 index.js에 코드를 작성했다. 그러나 계속해서 화면과 관련된 코드를 모두 index.js에 작성하면 코드 양이 기하급수적으로 늘어나게 된다. 리액트 개발에서는 기본적으로 화면 요소를 다양한 수준의 컴포넌트로 분할함으로써 재사용과 유지보수성을 높인다.
컴포넌트 분할
그럼 컴포넌트 만드는 과정에 대해 알아보자!
먼저 src 파일 폴더 아래 App.js라는 파일을 새로 만든다.
추가한 App.js에 index.js에 작성한 App 함수를 입력한다.
const App = () => {
return (
<>
<h1>Hello!</h1>
<p>안녕하세요!</p>
</>
);
};
그러나 이 상태로는 함수 컴포넌트를 이 파일 안에서만 사용할 수 있으므로 다른 파일에서도 사용할 수 있도록 export 해야 한다.
export const App = () => {
return (
<>
<h1>Hello!</h1>
<p>안녕하세요!</p>
</>
);
};
export 한 것을 import 하면 다른 파일 안에서도 사용할 수 있으므로 index.js에 작성한 App 함수는 삭제한다.
// index.js
import ReactDOM from "react-dom";
import { App } from "./App";
ReactDOM.render(<App />, document.getElementById("root"));
같은 계층에 있는 App.js로부터 App이라는 이름의 함수 컴포넌트를 읽었을 때는 이와 같이 작성한다. 확장자는 생략할 수 있다. 이렇게 각 파일에 컴포넌트를 정의하고, 다른 파일에서 읽어 부품을 조합하는 것처럼 화면을 만들어가는 것이 리액트 개발의 묘미 중 하나이다.
참고로 컴포넌트의 이름은 항상 대문자로 시작해야 된다. 왜냐하면 리액트는 소문자로 시작하는 컴포넌트를 DOM 태그로 인식하기 때문이다.