React에서 1개의 부모요소를 반환해야 한다는 조건으로 인해 이를 위한 다양한 방법이 존재하는데 해당 방법들을 배워보고 React하면 빠질수 없는 Fragment개념을 이번 포스팅에서 배워보자.
JSX
는 컴포넌트에서 반환하는 HTML코드이다.
const Info = (): JSX.Element => {
return (
<div>
<div>Hello World!</div>
</div>
);
};
하지만 JSX
에는 제한사항이 있다.
JSX
는 반환하는 루트요소가 무조건 1개여야 한다.
const Info = (): JSX.Element => {
return (
<div>
<div>Hi World!</div>
</div>
<div>
<div>Hello World!</div>
</div>
);
};
위 코드처럼 반환하는 루트요소가 2개인 경우 에러가 발생하게 된다.
따라서 여러개의 루트요소를 반환하려면 모든 요소들을 하나로 묶는 부모 요소를 만들어야 한다.
혹은 다른 방법으로 JSX배열
을 사용할 수 있다.
const Info = (): JSX.Element[] => {
return [
<div key="key1">
<div>Hi World!</div>
</div>,
<div key="key2">
<div>Hello World!</div>
</div>,
];
};
위와같이 반환 JSX
루트 요소들을 하나의 원소로 취급하여서 배열 형태로 바꿔주는 것이다.
하지만 이 방법은 각각의 루트요소에 구분을 위해서 key
속성을 넣어줘야 한다는 단점이 있다.
또한 위 방식은 코드의 가독성이 현저히 떨어지는 단점도 있다.
이를 위해서 쓸데없는 div지옥을 만들지 않고 해결할 수 있는 2가지 방법이 있다.
위 방법은 편법(?)으로 div요소를 만들지 않고 부모요소를 감싸줄 수 있다.
먼저 반환값인 JSX
요소들을 감싸줄 컴포넌트를 만들어준다.
const Wrapper = (props) => {
return props.children;
};
export default Wrapper;
그 후, 만든 Wrapper
를 사용하고자 하는 컴포넌트에 div대신 감싸준다.
import Wrapper from "../Wrapper";
const Info = (): JSX.Element => {
return (
<Wrapper>
<div>
<div>Hi World!</div>
</div>
<div>
<div>Hello World!</div>
</div>
</Wrapper>
);
};
export default Info;
그럼 신기하게도 div요소로 감싸지는 형식이 아니다.
즉, DOM렌더링
을 하지 않는다.
다만 이 방식의 단점이라고는 감싸줄 컴포넌트를 하나 만들어 줘야 한다는 점과 React + JavaScript에서만 유용하다고 느끼고 React + TypeScript조합에서는 사용하기가 다소 까다로울 것이다.
이를 위해 React에서는 위의 Wrapper
처럼 별도의 컴포넌트를 만들지 않아도 루트요소들을 div요소로 감싸지 않는 기능이 있다.
Wrapper
같은 부모요소를 직접 만들 필요 없이 React에서 제공하는 기능인 Fragment Component
를 알아보자.
Fragment
를 사용하기 위해서 해당 컴포넌틀 import해준다.
import { Fragment } from "react"
그 후, 감싸고 싶은 루트요소들을 Fragment
로 감싸주면 된다.
import { Fragment } from "react";
const Main = () => {
return (
<Fragment>
<div key="key1">
<div>Hello world!</div>
</div>
<div key="key2">
<div>Hello WOrld!</div>
</div>
</Fragment>
);
};
export default Main;
혹은 Fragment
를 import하지 않고 <>루트요소들</>
형식으로 사용해도 된다.
const Main = () => {
return (
<>
<div key="key1">
<div>Hello world!</div>
</div>
<div key="key2">
<div>Hello WOrld!</div>
</div>
</>
);
};
export default Main;
Wrapper
와 마찬가지로 쓸데없는 div로 감싸지는게 아닌 DOM렌더링
을 확인할 수 있다.
React는 변경 전 virtualDOM
과 변경 후 virtualDOM
의 비교를 통해서 요소들의 변경점을 모아서 실제DOM에 적용시킨다.
그럼 비교를 위해서 혹은 변경된 노드를 추적하기 위해서는 각각의 노드를 탐색해야 하는 과정이 필요하다.
따라서 부모 요소를 하나만 생성하여 DOM트리 탐색 과정을 수월하게 하기위해서 부모 요소를 하나만 반환하도록 하는 것이다.
Fragment는 프로젝트를 하다보면 자주사용하기 때문에 React를 배우기로 마음 먹었다면 무조건 알고 가야하는 개념으로 생각한다.
딱히 어려운 개념도 아니기 때문에 학습에 어려움도 없어서 짧은시간에 많은 효율성을 챙길 수 있다.
다만 모든 컴포넌트에 Fragment를 적용하기 보다는 필요한 부분에만 사용하는걸 추천하다.
왜냐.. style를 적용하다보면 Fragment보다는 요소로 감싸주기보다 목적이 있는 요소로 감싸주는게 오히려 요소 구성에 더 이득이 될 경우도 다수 발생하기 때문이다.