React JSX로 UI 표현하기
-> JSX 문법과 주의사항, 스타일 적용 방법
이번에는 React에서 화면을 표현할 때 사용하는 JSX에 대해 알아보겠습니다.
React 컴포넌트에서는 JavaScript 함수 안에서 HTML과 비슷한 형태의 코드를 작성할 수 있습니다.
이러한 문법을 JSX라고 합니다.
1. JSX란?
JSX는 JavaScript Syntax Extension의 약자로, JavaScript를 확장한 문법입니다.
React에서는 JSX를 사용하여 JavaScript 코드 안에서 HTML과 비슷한 문법으로 UI를 표현할 수 있습니다.
예를 들어 일반적인 JavaScript 코드에서는 다음과 같이 작성합니다.
const Main = () => {
return '<h1>main</h1>'
}
하지만 JSX를 사용하면 다음과 같이 HTML 태그와 비슷한 형태로 UI를 작성할 수 있습니다.
const Main = () => {
return (
<main>
<h1>main</h1>
</main>
)
}
JSX는 HTML과 매우 비슷하게 보이지만 JavaScript 안에서 사용되는 문법이라는 점이 중요합니다.
따라서 HTML과 완전히 동일하지 않고 몇 가지 작성 규칙이 존재합니다.
2. JSX에서 JavaScript 사용하기
JSX 안에서는 중괄호 {}를 사용하여 JavaScript 값을 화면에 표현할 수 있습니다.
예를 들어 변수를 만들어 보겠습니다.
const Main = () => {
const number = 10
return (
<main>
<h1>main</h1>
<h2>{number}</h2>
</main>
)
}
number 변수의 값은 10이므로 화면에 다음과 같이 표시됩니다.
main
10
중괄호 안에서는 JavaScript 표현식을 사용할 수 있습니다.
예를 들어 삼항 연산자를 사용할 수 있습니다.
const Main = () => {
const number = 10
return (
<main>
<h1>main</h1>
<h2>{number % 2 === 0 ? '짝수' : '홀수'}</h2>
</main>
)
}
number가 10이므로 화면에는 다음과 같이 표시됩니다.
main
짝수
3. JSX 작성 시 주의사항
JSX를 사용할 때는 몇 가지 중요한 규칙이 있습니다.
3-1. 중괄호 안에는 JavaScript 표현식만 사용할 수 있다
JSX에서 {} 안에는 값을 만들어낼 수 있는 JavaScript 표현식(Expression)을 사용할 수 있습니다.
예를 들어 다음과 같은 코드는 사용할 수 있습니다.
{number}
{number + 10}
{number % 2 === 0 ? '짝수' : '홀수'}
{obj.name}
반면 if, for, while과 같은 문장은 JSX 중괄호 안에서 직접 사용할 수 없습니다.
{
if (number > 10) {
...
}
}
if, for, while은 값을 반환하는 표현식이 아니라 제어문(Statement)이기 때문입니다.
조건에 따라 다른 내용을 표현하고 싶다면 삼항 연산자를 사용할 수 있습니다.
{number > 10 ? '10보다 큼' : '10 이하'}
또는 JSX를 반환하기 전에 별도로 조건문을 작성할 수도 있습니다.
const Main = () => {
const number = 10
let result
if (number % 2 === 0) {
result = '짝수'
} else {
result = '홀수'
}
return (
<main>
<h1>{result}</h1>
</main>
)
}
3-2. 모든 JavaScript 값이 화면에 렌더링되는 것은 아니다
JSX에서 {}를 이용해 값을 화면에 표현할 수 있지만 모든 값이 그대로 렌더링되는 것은 아닙니다.
대표적으로 문자열과 숫자는 렌더링할 수 있습니다.
const name = 'React'
const number = 10
return (
<main>
<p>{name}</p>
<p>{number}</p>
</main>
)
화면에는 다음과 같이 표시됩니다.
React
10
배열도 렌더링할 수 있습니다.
const fruits = ['사과', '바나나', '딸기']
return (
<main>
{fruits}
</main>
)
배열의 각 값이 화면에 표시됩니다.
반면 객체 자체를 JSX에서 바로 렌더링할 수는 없습니다.
const obj = {
a: 1,
b: 2,
}
return (
<main>
{obj}
</main>
)
객체 자체를 렌더링하려고 하면 오류가 발생합니다.
하지만 객체의 특정 프로퍼티 값은 렌더링할 수 있습니다.
const obj = {
a: 1,
b: 2,
}
return (
<main>
{obj.a}
</main>
)
화면에는 다음과 같이 표시됩니다.
1
또한 다음 값들은 일반적인 텍스트처럼 화면에 렌더링되지 않습니다.
{true}
{false}
{undefined}
{null}
이러한 특징은 조건부 렌더링을 할 때 많이 활용됩니다.
예를 들어 false일 경우 화면에 아무것도 표시하지 않는 특징을 이용할 수 있습니다.
3-3. 모든 태그는 닫아야 한다
HTML에서는 일부 태그를 닫지 않고 작성할 수 있는 경우가 있지만 JSX에서는 모든 태그를 닫아야 합니다.
예를 들어 다음과 같은 코드는 올바르지 않습니다.
<img src="image.png">
JSX에서는 반드시 태그를 닫아야 합니다.
<img src="image.png" />
input, br, hr과 같이 자식 요소가 없는 태그도 동일합니다.
<input />
<br />
<hr />
일반 태그 역시 반드시 닫아야 합니다.
<div>
<h1>안녕 리액트</h1>
</div>
3-4. 최상위 요소는 하나여야 한다
컴포넌트가 반환하는 JSX는 하나의 최상위 요소로 감싸져 있어야 합니다.
예를 들어 다음 코드는 오류가 발생합니다.
return (
<h1>header</h1>
<p>안녕하세요.</p>
)
두 개의 태그가 같은 레벨에 존재하기 때문입니다.
따라서 하나의 부모 태그로 감싸야 합니다.
return (
<div>
<h1>header</h1>
<p>안녕하세요.</p>
</div>
)
하지만 단순히 묶기 위해 불필요한 div를 추가하고 싶지 않을 수도 있습니다.
이럴 때 Fragment를 사용할 수 있습니다.
return (
<>
<h1>header</h1>
<p>안녕하세요.</p>
</>
)
<> </>는 React의 Fragment 축약 문법입니다.
여러 요소를 하나로 묶어 JSX 규칙을 만족시키면서도 실제 DOM에 불필요한 태그를 추가하지 않을 수 있습니다.
4. JSX 예제
지금까지의 내용을 하나의 코드로 정리하면 다음과 같습니다.
const Main = () => {
const number = 10
const obj = { a: 1 }
return (
<main>
<h1>main</h1>
<h2>{number % 2 === 0 ? '짝수' : '홀수'}</h2>
{true}
{undefined}
{null}
{obj.a}
</main>
)
}
export default Main
각 값은 다음과 같이 동작합니다.
코드결과
| {number % 2 === 0 ? '짝수' : '홀수'} | 짝수 렌더링 |
| {true} | 렌더링되지 않음 |
| {undefined} | 렌더링되지 않음 |
| {null} | 렌더링되지 않음 |
| {obj.a} | 1 렌더링 |
| {obj} | 객체 자체는 렌더링할 수 없음 |
5. JSX에서 스타일 적용하기
React에서 JSX로 UI를 작성할 때 스타일을 적용하는 방법은 크게 두 가지가 있습니다.
- 태그에 직접 style 속성을 작성하는 방법
- 별도의 CSS 파일을 만들어 적용하는 방법
5-1. 태그에 직접 스타일 적용하기
첫 번째 방법은 style 속성을 사용하는 방법입니다.
일반 CSS에서는 다음과 같이 작성합니다.
background-color: red;
font-size: 20px;
하지만 JSX에서는 JavaScript 객체 형태로 스타일을 작성합니다.
<h1
style={{
backgroundColor: 'red',
fontSize: '20px',
}}
>
안녕 리액트
</h1>
여기서 중요한 점은 CSS 속성 이름입니다.
일반 CSS에서는 background-color처럼 하이픈(-)을 사용하지만 JSX의 style 객체에서는 camelCase(카멜 케이스)를 사용합니다.
예를 들어 다음과 같이 변경됩니다.
CSSJSX style
| background-color | backgroundColor |
| font-size | fontSize |
| margin-top | marginTop |
| border-radius | borderRadius |
즉, JSX에서는 다음과 같이 작성합니다.
style={{
backgroundColor: 'red',
fontSize: '20px',
marginTop: '10px',
}}
6. 별도의 CSS 파일 사용하기
두 번째 방법은 별도의 CSS 파일을 만들어 스타일을 적용하는 방법입니다.
예를 들어 App.css에 다음과 같이 작성합니다.
.title {
background-color: red;
font-size: 20px;
}
그리고 React 컴포넌트에서 CSS 파일을 import 합니다.
import './App.css'
그다음 JSX에서 해당 클래스를 적용합니다.
일반 HTML에서는 다음과 같이 작성합니다.
<div class="logout">로그아웃</div>
하지만 JSX에서는 class 대신 **className**을 사용해야 합니다.
<div className="logout">로그아웃</div>
이는 JSX가 JavaScript와 함께 사용되는 문법이기 때문에 HTML의 class 속성 대신 className을 사용하기 때문입니다.
따라서 React에서 CSS 클래스를 적용할 때는 다음과 같이 작성합니다.
<h1 className="title">안녕 리액트</h1>
CSS 파일에서는 다음과 같이 작성합니다.
.title {
background-color: red;
font-size: 20px;
}
7. JSX 스타일링 방법 비교
두 가지 방법을 비교하면 다음과 같습니다.
1. Inline Style
<h1 style={{ color: 'red' }}>안녕 리액트</h1>
간단한 스타일을 빠르게 적용할 수 있습니다.
다만 스타일이 많아지면 JSX 코드가 길어지고 복잡해질 수 있습니다.
2. CSS 파일 사용
<h1 className="title">안녕 리액트</h1>
.title {
color: red;
}
JSX와 스타일을 분리할 수 있기 때문에 여러 스타일을 관리하기 편합니다.
마무리
이번에는 React에서 UI를 표현하는 JSX에 대해 알아보았습니다.
JSX는 HTML과 비슷한 문법을 사용하지만 JavaScript 안에서 동작하기 때문에 몇 가지 중요한 규칙이 있습니다.
정리하면 다음과 같습니다.
- JSX는 JavaScript 안에서 UI를 작성하기 위한 문법이다.
- {} 안에는 JavaScript 표현식을 사용할 수 있다.
- if, for, while 같은 제어문은 JSX 중괄호 안에서 직접 사용할 수 없다.
- 문자열과 숫자는 화면에 렌더링할 수 있다.
- 객체 자체는 렌더링할 수 없지만 객체의 프로퍼티 값은 렌더링할 수 있다.
- true, false, undefined, null은 일반적인 화면 텍스트로 렌더링되지 않는다.
- 모든 JSX 태그는 반드시 닫아야 한다.
- 컴포넌트가 반환하는 JSX는 하나의 최상위 요소로 묶어야 한다.
- 불필요한 태그를 만들고 싶지 않을 때는 <> </> Fragment를 사용할 수 있다.
- JSX에서 inline style은 JavaScript 객체 형태로 작성하며 CSS 속성은 camelCase를 사용한다.
- CSS 클래스를 적용할 때는 HTML의 class 대신 **className**을 사용한다.
React에서 컴포넌트를 만들고 JSX로 UI를 표현하는 방법을 이해했다면, 다음 단계에서는 JSX를 이용해 조건에 따라 다른 화면을 표시하거나 여러 데이터를 반복해서 렌더링하는 방법도 학습할 수 있습니다.