React의 모든 것 - 01 리액트의 탄생
목차
- React의 탄생 배경
- React의 핵심 구조
- React 요소 생성하기
- 실전에서의 React 개발
- React의 내부 동작 이해하기
React의 탄생 배경
Facebook의 도전과 혁신
흥미로운 시작
2010년대 초반, Facebook 개발팀은 "phantom messages"라는 흥미로운 문제에 직면했습니다. 메시지 아이콘 옆에 새로운 메시지를 나타내는 알림 배지가 표시되었지만, 클릭해보면 실제로는 새 메시지가 없었습니다.
이 단순해 보이는 문제는 사실 현대 웹 개발의 핵심적인 도전 과제를 대표하고 있었습니다
주요 도전 과제
- UI 상태 관리의 복잡성
- 여러 개발팀 간의 코드 통합 문제
- 빠른 개발 주기와 안정성 사이의 균형
이러한 도전 과제를 해결하기 위해 Facebook 팀은 완전히 새로운 접근 방식이 필요하다고 판단했고, 이것이 바로 React의 시작이었습니다.
React의 핵심 구조
두 개의 핵심 패키지
React는 크게 두 가지 핵심 패키지로 구성되어 있습니다
1. React Core (react)
- 컴포넌트 정의
- 상태 관리
- 생명주기 관리
- 이벤트 처리
- Virtual DOM 알고리즘
2. React DOM (react-dom)
- 실제 DOM 조작
- 브라우저 특화 기능
- 이벤트 시스템 통합
- 성능 최적화
React의 강점
이러한 분리는 React의 가장 큰 장점 중 하나입니다. React Core는 플랫폼에 독립적이어서, 웹뿐만 아니라 모바일(React Native), VR(React 360), 데스크톱(Electron) 등 다양한 환경에서 동일한 개발 경험을 제공할 수 있습니다.
React 요소 생성하기
createElement API 이해하기
React의 가장 기본적인 API는 createElement
입니다. JSX가 없던 시절에는 모든 React
개발자가 이 API를 직접 사용했죠. 지금도 모든 JSX 코드는 내부적으로 이 API 호출로 변환됩니다.
createElement 데모
// 기본 사용법
const element = React.createElement(
'div',
{ className: 'container' },
'Hello World',
);
// 중첩된 구조
const nestedElement = React.createElement(
'div',
{ className: 'container' },
React.createElement('h1', null, '제목'),
React.createElement('p', null, '내용'),
);
Props의 이해
Props(Properties)는 React의 핵심 개념 중 하나입니다. 컴포넌트에 전달되는 모든 데이터를 포함합니다
Props 데모
const buttonElement = React.createElement('button', {
className: 'primary-button',
onClick: () => alert('클릭!'),
disabled: false,
children: '클릭하세요',
});
Props의 특별한 기능
- 단일 값으로 전달 가능
- 배열로 여러 자식 전달 가능
- createElement의 세 번째 인자 이후로 전달 가능
복잡한 구조 만들기
실제 애플리케이션에서는 더 복잡한 구조를 만들어야 할 때가 많습니다. 예를 들어, 다음과 같은 구조를 만들어보겠습니다
복잡한 구조 데모
Here's Sam's favorite food:
- Green eggs
- Ham
<div class="container">
<p>Here's Sam's favorite food:</p>
<ul class="sams-food">
<li>Green eggs</li>
<li>Ham</li>
</ul>
</div>
React로 구현하면 다음과 같습니다
createElement(
'div',
{ className: 'container' },
createElement('p', null, "Here's Sam's favorite food:"),
createElement(
'ul',
{ className: 'sams-food' },
createElement('li', null, 'Green eggs'),
createElement('li', null, 'Ham'),
),
);
실전에서의 React 개발
개발 환경 설정
실제 프로덕션 환경에서는 다음과 같은 도구들이 필수적입니다
1. 패키지 관리자
- npm 또는 yarn
- 의존성 관리
- 스크립트 자동화
2. 빌드 도구
- webpack/Rollup
- Babel
- TypeScript
3. 개발자 도구
- React DevTools
- 상태 관리 도구
- 성능 프로파일링
기본적인 React 앱 구조
다음은 가장 기본적인 React 애플리케이션의 구조입니다
// 1. 의존성 임포트
import React from 'react';
import { createRoot } from 'react-dom/client';
// 2. 컴포넌트 정의
function App() {
return React.createElement(
'div',
null,
React.createElement('h1', null, '안녕하세요!'),
React.createElement('p', null, 'React의 세계에 오신 것을 환영합니다.'),
);
}
// 3. 렌더링
const container = document.getElementById('root');
const root = createRoot(container);
root.render(React.createElement(App));
React의 내부 동작 이해하기
React 요소의 해부학
React 요소를 콘솔에 출력해보면 다음과 같은 구조를 볼 수 있습니다
{
$$typeof: Symbol(react.element),
type: "div",
props: {
className: "container",
children: [
{
type: "h1",
props: { children: "제목" },
// ...기타 내부 속성들
}
]
},
// ...기타 내부 속성들
}
이 구조는 React가 어떻게 UI를 표현하고 관리하는지 보여줍니다
- $$typeof: XSS 공격 방지를 위한 심볼
- type: HTML 태그명 또는 React 컴포넌트
- props: 컴포넌트에 전달되는 모든 데이터
간단한 렌더링 구현
React의 동작 원리를 이해하기 위해, 매우 기본적인 수준의 렌더링 함수를 직접 구현해볼 수 있습니다
렌더링 데모
function simpleRender(reactElement, container) {
// 1. DOM 요소 생성
const domElement = document.createElement(reactElement.type);
// 2. 속성 설정
Object.keys(reactElement.props)
.filter((key) => key !== 'children')
.forEach((key) => {
domElement[key] = reactElement.props[key];
});
// 3. 자식 요소 처리
if (reactElement.props.children) {
if (typeof reactElement.props.children === 'string') {
domElement.textContent = reactElement.props.children;
} else {
reactElement.props.children.forEach((child) =>
simpleRender(child, domElement),
);
}
}
// 4. DOM에 추가
container.appendChild(domElement);
}
주의사항
위 구현은 단순화된 버전입니다. 실제 React의 렌더링 로직은 훨씬 더 복잡하며, 다양한 최적화와 기능들을 포함하고 있습니다.
결론
React의 성공 비결
1. 선언적 프로그래밍
UI를 어떻게 변경할지가 아닌, 어떤 상태여야 하는지 선언
2. 컴포넌트 기반
재사용 가능한 UI 조각으로 애플리케이션 구성
3. Learn Once, Write Anywhere
다양한 플랫폼에서 동일한 원칙 적용