오늘은 React JS 나 Next JS에서 사용되는 JSX에 대해서 정리해 보도록 하겠습니다.
1. JSX
JSX는 Javascript의 extention 인데요.
Javascript 파일안에서,
HTML과 유사한 마크업언어를 사용하도록 해 줍니다.
기존의 HTML지식에, 몇가지 사용 규칙들만 알면 쉽게 익숙해질 수 있습니다.
2. JSX 사용 규칙들
2-1. 하나의 root attribute 를 return
JSX에서는 괄호 () 안에 HTML 태그를 넣어 UI를 만들어야 합니다.
이때 모든 태그는 하나의 루트 엘리먼트로 감싸져야 해요.
예를 들어, 여러 태그를 <div>와 같은 한 개의 루트 엘리먼트로 묶어서 사용합니다.
아래에서는 <main>태그를 루트 엘리먼트로 사용하였네요.
const right = (
<main>
<div>
<p>테스트1을 시작합니다</p>
<p>테스트2를 시작합니다</p>
</div>
</main>
);
위에서 사용된 main 태그와 같은 루트 엘리먼트를 프래그먼트라고 부를 수 있어요.
복잡한 내용이 아니라면, <></>와 같은 빈 태그를 사용해도 됩니다.
이런 빈 태그는 단순히 여러 요소들을 하나로 묶는 컨테이너 역할만 해주기 때문이에요.
const emptyFragment = (
<>
<div>
<p>Hello World</p>
</div>
</>
);
아래는 잘못된 사례인데요.
아래와 같이 여러개의 attribute을 넣고 괄호를 닫으면 에러가 발생합니다.
const wrong = (
<>
<p className="test1">테스트1을 시작합니다</p>
<p className="test2">테스트2를 시작합니다</p>
</>
);
2-2. tag를 항상 닫기
jsx에서는 tag를 반드시 닫도록 되어 있습니다.
<img>태그 같은 경우에도 반드시 <img/>와 같이 해 주어야 하구요.
<ul>, <ol>, <li> 등도 아래와 같이 </ul>, </ol>, </li> 와 같이 닫아주어야 합니다.
JSX에서는 모든 태그를 반드시 닫아야 해요.
예를 들어, <img> 태그는 <img/>처럼 닫아줘야 합니다.
<ul>, <ol>, <li> 같은 태그들도 각각 </ul>, </ol>, </li>와 같이 끝을 명확하게 닫아 주어야 합니다.
이렇게 태그를 닫는 것은 꼭 지켜야 할 JSX의 규칙 중 하나입니다.
<>
<img
src="https://test.jpg"
className="photo"
/>
<ul>
<li>아이템1</li>
<li>아이템2</li>
<li>아이템3</li>
</ul>
</>
2-3. css class 및 id 적용
HTML에서 CSS 클래스를 적용할 때는 class 속성을 사용했습니다.
하지만 JSX에서는 className을 사용해야 합니다.
JSX에서 class 대신 'className'을 사용하는 것을 잊지 마세요.
const right = (
<main>
<div className="beauty">
<p className="test1">hello world</p>
</div>
</main>
);
JSX에서 id 속성을 사용할 때는 HTML과 동일하게 id를 그대로 사용하면 됩니다.
예를 들어, JSX에서 특정 엘리먼트에 ID를 부여하려면 다음과 같이 작성합니다:
const App = () => {
return (
<div id="myid">ui테스트</div>
);
};
2-4. Javascript부분은 { }를 사용
HTML태그안에서, Javascript 를 사용할 때는,
중괄호 '{ }'를 사용해 주면 됩니다.
const add = (a, b) => a + b;
export default function calc() {
return (
<div>
<p>The sum of 1 and 7 is {add(1, 7)}</p>
</div>
);
}
아래와 같이 객체를 만들어서 접근하는 것도 가능합니다.
const person = {
name: 'kim gun'
};
export default function test() {
return (
<div>
<h1>Hello, {person.name}!</h1>
</div>
);
}
2-5. Inline style의 표현
JSX에서 CSS 스타일을 직접 적용할 때는 {{ }}를 사용해요.
바깥쪽 중괄호는 JSX 안에서 JavaScript 코드를 쓰기 위한 것이고,
안쪽 중괄호는 JavaScript 객체를 의미합니다.
inline 스타일을 적용하려면 아래와 같이 사용해 주면 됩니다.
export default function TodoList(){
return (
<ul style={{ backgroundColor: 'navy', color: 'white' }}>
<li>아이템1</li>
<li>아이템2</li>
<li>아이템3</li>
</ul>
);
}
한가지 주의할 점은,
css 중에는 중간에 '-'가 들어가는 경우가 있습니다.
이 때는 javascript의 CamelCase를 사용해서 넣어주면 됩니다.
예를 들어, 위에서 사용된 'backgroundColor'는 원래 css에서는 'background-color'가 맞습니다.
하지만, jsx의 규칙에 따라서, camelCase로 변경하여 집어넣었습니다.
JSX에서 CSS 스타일을 적용할 때 주의할 점이 있어요.
CSS에 하이픈(-)이 들어가는 속성들은 JSX에서는 카멜 케이스로 변경해야 합니다.
예를 들어, CSS의 background-color는 JSX에서 backgroundColor로 써야 해요.
이는 JSX에서 JavaScript 객체를 사용해 스타일을 정의하기 때문입니다.
따라서, CSS가 아닌, JavaScript의 네이밍 규칙을 따라야 하는 것 이지요.
2-6. EventListener
JSX에서 이벤트 리스너를 사용하는 방법은 간단합니다.
예를 들어, 클릭 이벤트를 처리하려면 onClick 속성을 사용한다고 가정해 보겠습니다.
이벤트 처리 함수를 정의하고, 해당 함수를 onClick 속성에 적용하면 되는데요.
Javascript 함수이므로, 위에서 본 것처럼 { } 를 사용해 주면 됩니다.
const handleClick = () => {
alert('클릭됨!');
};
const App = () => {
<div>
<button onClick={handleClick}>확인</button>
</div>
}
2-7. if문
JSX에서는 아래와 같이 return 문 바깥에서, if문을 사용할 수 있습니다.
const MyComponent = ({ isLoggedIn }) => {
if (isLoggedIn) {
return <div>환영합니다!</div>;
} else {
return <div>로그인 해 주세요.</div>;
}
}
return 문 안에서 삼항연산자(ternary)를 이용해,
조건에 따라 다른 UI를 보여주도록 할 수도 있습니다.
const MyComponent = ({ isLoggedIn }) => {
return (
<div>
{isLoggedIn ? <p>환영합니다.!</p> : <p>로그인 해 주세요</p>}
</div>
);
}
아래 예제에서 isHidden이 true이면, 컴포넌트는 null을 반환하여 아무것도 렌더링하지 않습니다.
이 방법은 조건에 따라 특정 컴포넌트를 화면에 표시하지 않고 싶을 때 유용합니다.
null을 반환함으로써 컴포넌트가 전혀 렌더링되지 않도록 하는 것이죠.
const ListItem = ({ isHidden, name }) => {
if (isHidden) return null;
return <li className="item">{name}</li>;
}
2-8. 리스트 표현(map)
jsx에서는 Javascript es6의 map 연산자도 사용할 수 있는데요.
다음과 같이 활용해서 리스트를 표현할 수 있습니다.
const FruitList = () => {
const fruits = ['banana', 'apple', 'pineapple'];
return (
<div>
<p>과일의 개수는 {fruits.length}개입니다.</p>
<ul role="list">
{fruits.map((fruit) => (
// Assuming each fruit is unique in this list
<li key={fruit} role="listitem">{fruit}</li>
))}
</ul>
</div>
);
}
참고로 위에서 사용된 key는 react에서 리스트의 아이템을 트래킹하기 위해 사용하는 것 입니다.
html에 보여지는 부분은 아닙니다.
그리고, <li>태그 앞뒤로, 소괄호()로 감싸고 있는 부분이 있는데요.
이것은 가독성을 위한 것으로, 꼭 필수인 부분은 아닙니다.
아래 예제에서는 소괄호()를 사용하지 않았습니다.
아래는 공식문서에 나오는 예 입니다.
import { people } from './data.js';
import { getImageUrl } from './utils.js';
export default function List() {
const chemists = people.filter(person =>
person.profession === 'chemist'
);
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
known for {person.accomplishment}
</p>
</li>
);
return <ul>{listItems}</ul>;
}
만약 리스트에 아이템이 없어서 아무것도 표시하지 않고자 할 때는,
리스트의 length를 체크해 길이가 0이면 null을 반환하면 됩니다.
이 방법을 이용해서 빈 리스트가 화면에 표시되지 않도록 할 수 있습니다.
const DynamicList = ({ items }) => {
if (items.length === 0) {
return null;
}
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
};
2-10. 다이나믹한 변수들 사용
아래와 같이 다이나믹하게 변하는 값들을 사용하기 위해서는,
Javascript 의 템플릿 리터럴(Template literals)을 사용해주면 됩니다.
(이전에는 Template String이라는 명칭을 사용했었습니다.)
주의할 것은, 따옴표로 감싸주는 것이 아니라,
백틱 (`) 이라고 불리는 것을 사용해서 감싸주는 것이구요.
다이나믹하게 변하는 값을 위한 javascript 표현식은,
아래와 같이 $와 중괄호( $ {expression} ) 로 표기해 주면 됩니다.
<img src={`${person.name}.jpg`} alt="description" />
3. 정리
JSX는 HTML과 같이 직관적으로 UI를 구성하면서 자바스크립트를 유연하게 섞어 쓸 수 있는 장점이 있어요.
하지만 코드가 복잡해지거나 가독성이 떨어질 수도 있지요.
HTML과는 조금 다른 규칙이 있어서,
className 사용이나 CSS에서의 카멜 케이스 사용처럼 주의할 점도 있습니다.
JSX를 이해하는데 도움이 되셨으면 좋겠네요.
댓글