리액트는 UI를 컴포넌트 단위로 구성한다.
컴포넌트는 쉽게 말해 "화면을 구성하는 작은 조각"이다. 버튼 하나, 헤더 하나, 목록 하나도 모두 컴포넌트다.
✅ 함수 컴포넌트란?
가장 일반적인 방식은 "함수(function)"을 이용해서 컴포넌트를 만드는 것이다.
예를 들어, 헤더 컴포넌트를 만든다면 다음과 같이 작성할 수 있다.
// 함수 선언식
function Header() {
return <header>헤더 입니다</header>
}
// 화살표 선언식
const Header = () => {
return <header>헤더 입니다</header>
};
함수 선언식, 화살표 선언식 모두 기능은 동일하기 때문에 익숙한 방식으로 사용하면 된다.
클래스를 이용해서 선언할 수 있지만 코드가 복잡해져서 함수 방식이 일반적으로 사용된다.
✅ 함수 컴포넌트의 return 문법 - 괄호와 태그
리액트 함수 컴포넌트는 JSX 를 return 으로 반환한다. 이때 작성 방식에 따라 괄호 사용법이 달라진다.
1. 한 줄일 경우 괄호 없어도 OK
const Hello = () => <h1>안녕하세요</h1>;
- JSX가 한 줄이면 괄호 없이 바로 반환 가능하다.
- 단, JSX 문법은 <태그>로 시작해야 한다.
2. 여러 줄이면 괄호로 감싸야 함
const Hello = () => (
<div>
<h1>안녕하세요</h1>
<p>만나서 반가워요</p>
</div>
);
- 여러 줄 JSX를 반환할 때는 괄호로 감싸야 한다.
- 이 괄호는 JavaScript 문법상의 우선순위 문제를 피하기 위한 것.
3. JSX는 반드시 하나의 태그로 감싸야 함
// 오류 발생
const Hello = () => (
<h1>안녕하세요<h1>
<p>만나서 반가워요</p>
);
// 올바른 예시
const Hello = () => (
<div>
<h1>안녕하세요</h1>
</p>만나서 반가워요</p>
</div>
)
<></> 같은 Fragment 문법으로도 감쌀 수 있음
이는 불필요한 DOM 요소를 만들지 않아서 자주 쓰인다
✅ 왜 JSX는 하나의 태그만 반환해야 할까?
JSX는 결국 React.createElement() 호출로 변환되는데, 하나의 컴포넌트는 단 하나의 요소만 반환해야 하기 때문이다.
여러 개의 요소를 반환하면 구조적으로 모호해져서 에러가 발생한다.
작성 형태 | 문법 | 설명 |
한 줄 JSX | return <태그 /> | 괄호 생략 가능 |
여러 줄 JSX | return (...) | 괄호로 감싸야 함 |
JSX 요소 여러 개 | <div>...</div> or <>...</> | 하나의 부모 요소로 감싸야 함 |
✅ 함수 컴포넌트에서 return을 생략할 수 있는 경우
🔹 한 줄인 경우 - return 생략 가능
const Hello = () => <h1>안녕하세요</h1>; // return 생략 가능
const Hello = () => {
return <h1>안녕하세요</h1>;
};
🔸 여러 줄인 경우
// 중괄호 {} 로 열면 return 필요
const Hello = () => {
return (
<div>
<h1>안녕하세요</h1>
<p>반가워요!</p>
</div>
);
};
// 괄호 () 안에 바로 JSX 넣으면 return 생략 가능
const Hello = () => (
<div>
<h1>안녕하세요</h1>
<p>반가워요!</p>
</div>
);
🚫 주의할 점
const Hello = () => {
// 괄호만 쓰고 return 안 쓰면 undefined 반환됨!
(
<h1>안녕하세요</h1>
);
};
작성 형태 | return 필요 여부 | 예시 |
한 줄 JSX | 생략 가능 | const A = () => <h1>Hi</h1>; |
여러 줄 JSX + 괄호 () | 생략 가능 | const A = () => ( <div>...</div> ); |
중괄호 {} 사용 | 필요 | const A = () => { return <div>...</div>; }; |
✅ 컴포넌트 이름 규칙
컴포넌트의 이름은 반드시 대문자로 시작해야 한다.
만약 소문자로 시작하면, 리액트는 이를 그냥 HTML 태그로 인식해버린다.
const header = () => <header>...</header>; // 잘못된 예시
✅ 컴포넌트를 사용하는 방법
컴포넌트는 태그처럼 사용할 수 있다.
const App = () => {
return (
<div>
<Header />
</div>
)
}
여기서 App 은 부모 컴포넌트, Header 는 자식 컴포넌트다.
✅ 루트 컴포넌트란 ?
모든 React 앱은 하나의 컴포넌트에서 출발한다.
이 컴포넌트를 루트 컴포넌트라고 부르는데, 관례상 이름은 App 을 사용한다.
루트 컴포넌트는 main.jsx 에서 렌더링된다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
리액트 앱에서 화면에 나타나는 모든 요소는 App 안에 포함돼야 한다.
App이 바로 렌더링의 출발점(조상 컴포넌트) 이기 때문이다.
✅ 컴포넌트 파일 분리
src/
├── App.jsx
├── components/
│ └── Header.jsx
// App.jsx
import Header from './components/Header';
function App() {
return (
<div>
<Header />
</div>
);
}
ES Modules 는 원칙상 import 시 확장자를 명시해야 하지만
Vite 같은 번들러가 생략을 가능하게 해줌
🔧 설정된 확장자 우선순위 리스트를 따라 해당 파일을 자동으로 찾아서 연결
'Node.js > React' 카테고리의 다른 글
[React] JSX로 UI 표현하기 (0) | 2025.05.05 |
---|---|
[React] React App 구동원리 알아보기 (0) | 2025.05.04 |
[React] React App 생성하기 (0) | 2025.05.04 |
[React] 리액트란 무엇인가? (0) | 2025.05.04 |
[React] Quick Start - 1 (0) | 2025.02.18 |