React와 함께 빌드하기: JSX, 컴포넌트, 그리고 Props에 뛰어들다! (React Day 2)
I’m happy to help translate the article, but I’ll need the full text you’d like translated. Could you please paste the content (excluding the source line you already provided) here? Once I have it, I’ll translate it into Korean while preserving the formatting, markdown, and any code blocks or URLs.
🎉 환영합니다, 이제는 프로가 된 React 초보자 여러분!
Day 1의 큰 그림 개요에 이어, 오늘은 React가 움직이는 핵심 요소들을 파헤칩니다:
- JSX – JavaScript 안에서 UI와 같은 마크업을 작성할 수 있게 해 주는 문법.
- 함수형 컴포넌트 – 현대 React의 기본 빌딩 블록.
- Props – 부모에서 자식으로 흐르는 읽기 전용 데이터.
- 재사용성 & 컴포지션 – 강력한 앱을 만들기 위해 컴포넌트를 연결하는 방법.
JSX를 자세히 설명하고, 순수 JavaScript와 비교하며, 베스트 프랙티스를 공유합니다. Day 3의 Vite 설정과 호환되는 실시간 코드 예시를 제공하고, 흔히 마주치는 함정들을 짚어보며, 핵심 흐름을 다이어그램으로 시각화합니다. 실제 상황을 통해 각 개념이 어떻게 적용되는지 보여줄 것입니다. 끝까지 따라오시면 숙련된 개발자처럼 UI를 만들 수 있게 됩니다. 컴포넌트화를 시작해봅시다!
📦 JSX (JavaScript XML)
JSX는 React의 문법 확장으로, JavaScript 안에 HTML‑like 코드를 직접 작성할 수 있게 해줍니다. 실제 HTML이 아니라 Babel이 이를
React.createElement호출로 변환합니다.
JSX가 중요한 이유
- 마크업과 로직을 자연스럽게 결합합니다.
- 수동 DOM 조작에 비해 가독성과 유지보수성이 향상됩니다.
내부 동작 과정
- Write JSX →
- Babel이 일반 JavaScript(
React.createElement)로 변환합니다. - React가 그 요소 객체들을 사용해 가상 DOM을 구축합니다.
실시간 예제
// JSX
const element = <h1>Hello, React!</h1>;
변환된 코드:
// JavaScript after Babel
const element = React.createElement('h1', null, 'Hello, React!');
컴포넌트에서 렌더링
import React from 'react';
function App() {
return <h1>Hello, React!</h1>;
}
이 코드를
src/App.jsx(또는App.tsx)에 붙여넣고npm run dev를 실행하세요. 헤딩이 즉시 표시됩니다.
JSX vs. 일반 JavaScript
| JSX | 일반 JavaScript |
|---|---|
{message} | React.createElement('div', null, message) |
| 간결하고 HTML‑친숙함 | 장황하고 중첩 구조를 시각화하기 어려움 |
핵심: JSX는 단순히 문법 설탕(syntactic sugar)일 뿐이며, 브라우저는 최종적으로 JavaScript 버전을 실행합니다.
다이어그램 – JSX 변환 과정
JSX code
│
▼ (Babel)
React.createElement calls
│
▼ (React runtime)
Virtual DOM → Real DOM
모범 사례
- Component names → PascalCase(
MyComponent). - Self‑closing tags →
<Component />. - Multi‑line returns → 괄호로 감싸기:
return (…);. - 인라인 스타일 객체보다 CSS classes 사용을 권장(필요할 때만 인라인 스타일 사용).
흔한 실수
JSX를 문자열처럼 취급하고 문자열을 이어 붙이는 경우. JSX는 objects를 생성하므로, 문자열 연결 대신 컴포넌트로 UI를 구성해야 합니다.
실제 적용 시나리오
블로그 앱에서 게시물 미리보기를 다음과 같이 렌더링합니다:
// Example placeholder – insert actual JSX for a post preview here
JSX를 사용하면 데이터(post.title)와 구조(<h2>{post.title}</h2>)를 손쉽게 섞어 사용할 수 있습니다.
⚛️ 함수형 컴포넌트
함수형 컴포넌트는 JSX를 반환하는 순수 JavaScript(또는 TypeScript) 함수입니다. React 16.8(훅) 이후로 기본 선택이 되었으며, 대부분의 클래스 컴포넌트를 대체합니다.
왜 함수형인가?
- 더 간단한 문법,
this바인딩이 필요 없음. - 상태, 부수 효과, 컨텍스트 등을 위해 Hooks와 완벽하게 짝을 이룹니다.
실시간 예제
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
function App() {
return <Welcome name="Sara" />;
}
“Hello, Sara!”를 렌더링합니다.
구조화 팁
- 컴포넌트를 작게 유지 – 컴포넌트당 하나의 UI 관심사만 (단일 책임 원칙).
- 컴포넌트당 하나의 파일 –
export default로 내보냅니다. - 간결함을 위해 화살표 함수 사용:
const Button = () => <button>Click</button>;
- 폴더 구조 (확장 가능):
src/
└─ components/
└─ Button/
├─ index.jsx
└─ styles.module.css
흔한 실수
래퍼 없이 여러 형제 요소를 반환하는 경우. Fragments로 해결:
return (
<>
<div>One</div>
<div>Two</div>
</>
);
실제 시나리오
ProductCard 함수형 컴포넌트는 아이템의 이미지, 이름, 가격 및 “Add to Cart” 버튼을 표시합니다. 이 컴포넌트는 제품 그리드, 검색 결과, 추천 캐러셀 등에서 재사용됩니다.
📤 Props (Properties)
Props는 읽기 전용 데이터로, 부모 컴포넌트에서 자식 컴포넌트로 함수 인수처럼 전달됩니다. 동적인 재사용 가능한 UI를 가능하게 합니다.
Props 작동 방식
// Parent → Child
<Child name="Alice" age={30} />
// Child가 받음
function Child(props) {
return (
<p>{props.name} is {props.age} years old.</p>
);
}
실시간 예시
function Greeting(props) {
return (
<p>Hi, {props.name}! You are {props.age} years old.</p>
);
}
function App() {
return (
<>
<Greeting name="Bob" age={25} />
<Greeting name="Carol" age={28} />
</>
);
}
두 개의 맞춤 인사말이 표시됩니다. Props는 단방향 흐름(parent → child)입니다.
흔히 발생하는 실수
| Issue | Why it’s a problem | Fix |
|---|---|---|
Mutating props (props.name = 'New') | 불변성을 깨뜨려 재렌더링이 일어나지 않음. | state를 사용해 가변 데이터를 관리합니다. |
| Missing defaults | undefined 값이 발생합니다. | defaultProps를 제공하거나 디스트럭처링에 기본값을 지정: function Comp({ name = 'Guest' }) { … }. |
No key in lists | React가 항목을 효율적으로 추적하지 못합니다. | 고유한 key prop을 추가: <Item key={id} />. |
| Prop drilling (많은 레이어를 통해 전달) | 유지보수가 어려워집니다. | Context 혹은 상태 관리 라이브러리를 사용합니다. |
Props 흐름 시각화
Parent Component
│ passes props
▼
Child Component (receives props)
│ may pass further down
▼
Grandchild …
실제 적용 사례
소셜 미디어 피드에서 Post 컴포넌트는 다음과 같이 데이터를 받습니다:
<Post author={user} content={text} timestamp={date} />
이 컴포넌트는 하드코딩 없이 각 게시물을 렌더링합니다.
🔁 재사용성
재사용성은 컴포넌트를 한 번 작성하고 다양한 props 또는 설정으로 어디서든 사용할 수 있게 하는 것을 의미합니다.
달성 방법
- 범용 props를 받을 수 있도록 컴포넌트를 설계합니다.
- 내부 로직을 특정 데이터와 독립적으로 유지합니다.
실시간 예시 – 재사용 가능한 버튼
function Button({ label, color, onClick }) {
return (
<button style={{ backgroundColor: color }} onClick={onClick}>
{label}
</button>
);
}
function App() {
return (
<>
<Button label="Submit" color="green" onClick={() => alert('Submitted!')} />
<Button label="Cancel" color="red" onClick={() => alert('Canceled!')} />
</>
);
}
하나의 컴포넌트, 두 가지 뚜렷한 동작 → DRY하고 유연합니다.
모범 사례
- 선택적 props는 실제로 선택 가능하도록 하고(합리적인 기본값 제공).
- TypeScript 또는
prop-types를 사용해 prop 형태를 강제하고 오류를 조기에 잡아냅니다.
실제 시나리오
대시보드의 Chart 컴포넌트는 다음과 같이 사용됩니다:
<Chart type="line" data={salesData} options={chartOptions} />
같은 컴포넌트가 중복 없이 다양한 시각화를 렌더링합니다.
🧩 구성
구성은 컴포넌트를 중첩시켜 단순하고 재사용 가능한 조각들로부터 복잡한 UI를 만드는 기술입니다. 특수한 children prop은 유연한 “슬롯”을 가능하게 합니다.
작동 방식
- 부모가 JSX 안에서 자식을 감쌉니다.
- 자식은
{props.children}을 통해 이를 렌더링합니다.
실시간 예시 – Card 구성
function Card({ children }) {
return <div className="card">{children}</div>;
}
function App() {
return (
<Card>
<h2>Product Title</h2>
<p>Short description of the product.</p>
<button>Add to cart</button>
</Card>
);
}
Card는 레이아웃을 제공하고, 호출자는 내부 콘텐츠를 결정합니다.
장점
- 관심사의 분리 – 레이아웃 vs. 콘텐츠.
- 확장성 – 부모를 건드리지 않고도 어떤 자식이든 교체할 수 있습니다.
✅ TL;DR 체크리스트
- ✅ 읽기 쉬운 마크업을 위해 JSX를 사용하세요;
React.createElement로 컴파일된다는 점을 기억하세요. - ✅ 함수형 컴포넌트를 작성하세요; 작고 집중된 형태로 유지하세요.
- ✅ props를 부모 → 자식으로 읽기 전용으로 전달하세요; 변형을 피하세요.
- ✅ 컴포넌트를 재사용성을 위해 설계하세요 – 일반적인 props, TypeScript/prop‑types 사용.
- ✅ 컴포지션(
children)을 활용해 유연한 UI 구조를 만드세요.
이제 진행해서 재사용 가능한 Button, Card 래퍼, 그리고 몇 개의 Greeting 컴포넌트를 사용해 작은 UI를 만들어 보세요—위 예시와 같이. 즐거운 코딩 되세요! 🚀
컴포넌트 예시
function Card(props) {
return (
<div className="card">
<h2>{props.title}</h2>
{props.children}
</div>
);
}
function App() {
return (
<Card title="Profile">
<p>Name: Dana</p>
<p>Job: Developer</p>
</Card>
);
}
Card 컴포넌트는 임의의 콘텐츠를 조합합니다. 계층 구조를 위해 더 깊게 중첩할 수 있습니다.
모범 사례
- 구성(composition)을 상속보다 선호 – React는 클래스 기반 상속에 의존하기보다 작고 재사용 가능한 컴포넌트를 결합하여 UI를 구축하는 것을 장려합니다.
- 중첩을 논리적으로 유지 – 컴포넌트 트리가 너무 깊어지면, 더 작고 집중된 컴포넌트로 리팩터링하는 것을 고려하세요.
실제 시나리오
뉴스 앱에서 Article 컴포넌트는 다음으로 구성될 수 있습니다:
HeaderBodyComments
각 섹션은 다양한 스토리에서 재사용 가능하며, Article 컴포넌트는 맞춤형 내부 콘텐츠(예: 다른 레이아웃, 광고, 관련 링크)를 허용합니다.
요약 및 다음 단계
- JSX, 함수형 컴포넌트, props, 그리고 재사용/구성의 기술을 마스터했습니다 – 확장 가능한 React 앱의 핵심입니다.
- 직접 해보기: 위의
Card패턴을 사용해 미니 프로필 페이지를 만들어 보세요. - 공통 주제: UI를 선언적이고 모듈식으로 유지하세요.
- 실수에 막혔나요? React DevTools로 디버깅하세요.
다음: Day 3 – 상태와 라이프사이클!
지금까지 가장 마음에 드는 예시는 무엇인가요? 계속 만들어 보세요! 🚀