React는 UI(사용자 인터페이스)를 만들기 위한 자바스크립트 라이브러리입니다. 주로 단일 페이지 애플리케이션(SPA)과 클라이언트 사이드 렌더링(CSR)을 구현하는 데 사용됩니다.
왜 React는 라이브러리인가?
프레임워크는 보통 HTTP 클라이언트, 상태 관리(State Management), 라우팅(Routing), UI 등의 기능을 기본적으로 제공하여, 개발자가 이를 이용해 개발을 진행할 수 있게 합니다. 프레임워크를 사용하면 정해진 틀과 규칙에 따라 개발을 진행할 수 있어 편리하지만, 몇 가지 단점도 존재합니다.
먼저, 프레임워크에서 권장하는 모든 기능과 구조를 익혀야 하므로 초기 학습에 많은 시간이 필요합니다. 또한, 정해진 틀 내에서만 작업할 수 있기 때문에 자율성이 떨어지고, 개발자는 프레임워크가 제공하는 방식에 맞춰야만 합니다.
반면에 라이브러리는 큰 골격이나 규칙이 정의되지 않았으며, 특정 문제를 해결하기 위한 작은 솔루션 단위로 구성됩니다. React는 이러한 라이브러리의 성격을 가지고 있습니다.
React는 웹 애플리케이션을 만들 때 주로 UI 구축에 중점을 둔 라이브러리입니다. 예를 들어, 네트워크 통신이 필요하다면 브라우저에서 제공하는 fetch API나 다른 네트워크 라이브러리를 사용할 수 있습니다. 라우팅이 필요할 때는 별도의 라우팅 라이브러리를 선택하여 사용하면 됩니다. 이처럼, React는 필요한 기능을 선택해서 사용할 수 있는 자율성을 보장합니다.
또한, React는 UI와 관련된 문제만을 해결하는 라이브러리이기 때문에 배워야 할 내용이 상대적으로 적고, 진입 장벽이 낮습니다.
참고로, 웹 프레임워크 중에서 많이 사용되는 Vue.js는 프레임워크로 분류되지만, HTTP 통신이나 상태 관리 기능을 기본적으로 제공하지 않기 때문에 경량형 프레임워크로 볼 수 있습니다.
SPA (Single Page Application)
SPA는 하나의 HTML 페이지로 구성된 웹 애플리케이션을 의미합니다. React는 이러한 SPA를 쉽게 구현할 수 있도록 돕습니다. SPA는 초기 로드 시 모든 자바스크립트, CSS, HTML을 불러오고, 이후 페이지 간 이동은 추가적인 HTML 요청 없이 자바스크립트를 통해 동적으로 이루어집니다. 이로 인해 페이지 전환이 빠르고 원활합니다.
CSR (Client Side Rendering)
CSR은 클라이언트, 즉 브라우저에서 페이지를 렌더링하는 방식입니다. React는 CSR 방식을 채택하여, 서버가 기본 HTML과 자바스크립트 파일만 제공하고, 브라우저가 자바스크립트를 실행해 동적으로 DOM을 생성합니다. 이는 초기 로딩 시간이 길어질 수 있지만, 이후의 페이지 전환 속도가 빨라지는 장점이 있습니다.
컴포넌트(Component)
React는 UI를 작은 컴포넌트 단위로 나누어 구성하고, 사용자 이벤트에 반응하도록 만든 라이브러리입니다. 컴포넌트는 하나의 독립적인 UI 블록으로, 다른 컴포넌트와는 별개로 동작합니다. React로 웹 애플리케이션을 만든다는 것은, 이러한 UI 컴포넌트를 하나씩 만들어 조립해 나가는 과정입니다.
각 페이지에서 필요한 컴포넌트를 만들어, 이를 조립하여 전체 UI를 완성할 수 있습니다. 중요한 것은, 컴포넌트를 잘 설계하고 만드는 것입니다. 좋은 컴포넌트란 독립적이고 재사용성이 높은 컴포넌트를 의미합니다. 즉, 다른 컴포넌트에 영향을 받지 않으며, 여러 곳에서 다시 사용할 수 있어야 합니다.
컴포넌트는 재사용 가능한 로직이나 UI의 단일 책임을 가지는 것이 중요합니다. 만약 하나의 컴포넌트가 너무 많은 UI 요소를 포함하거나, 지나치게 복잡한 로직을 가지고 있다면, 이를 더 작은 단위의 컴포넌트로 나누는 것이 좋습니다. 이렇게 하면 코드의 가독성이 높아지고, 유지보수도 쉬워집니다.
결국, React는 이처럼 독립적이고 재사용 가능한 컴포넌트들로 이루어진 라이브러리입니다.
컴포넌트 사용 예제
다음은 간단한 함수형 컴포넌트 예제입니다. 이 컴포넌트는 name이라는 props를 받아서, "Hello, [name]!"이라는 텍스트를 출력합니다.
이 예제에서는 greeting이라는 상태를 관리하며, 버튼을 클릭하면 greeting이 "Hi"로 변경됩니다.
import React, { useState } from 'react';
export function Greeting(props) {
const [greeting, setGreeting] = useState('Hello');
return (
<div>
<h1>{greeting}, {props.name}!</h1>
<button onClick={() => setGreeting('Hi')}>Change Greeting</button>
</div>
);
}
이 컴포넌트를 실제로 사용해 보려면, 다음과 같이 사용할 수 있습니다:
import React from 'react';
import Greeting from './Greeting';
function App() {
return (
<div>
<Greeting name="Alice" />
<Greeting name="Bob" />
</div>
);
}
export default App;
JSX와 React 컴포넌트의 구성 요소
자바스크립트에서 함수의 반환값으로 HTML처럼 생긴 것을 반환할 수 있는 이유는, 바로 JSX이기 때문입니다. JSX는 자바스크립트 내에서 HTML 태그를 사용하는 것처럼 보이게 하는 문법으로, 실제로는 자바스크립트 객체로 변환됩니다. 이를 통해 우리가 원하는 컴포넌트를 마치 HTML처럼 작성할 수 있습니다.
React 컴포넌트는 주로 props, state, 그리고 render로 구성됩니다. props는 컴포넌트에 전달되는 데이터, state는 컴포넌트 내에서 관리되는 상태, 그리고 render는 이들을 조합해 UI를 출력하는 역할을 합니다.
상태 관리와 컴포넌트 업데이트
각각의 컴포넌트는 자신만의 상태(state)를 가지고 있습니다. 이 상태값이 업데이트되면, React는 자동으로 해당 상태값이 변경된 컴포넌트만 새롭게 업데이트해 줍니다. 이를 통해 효율적인 UI 렌더링이 가능하며, 불필요한 컴포넌트의 재렌더링을 방지할 수 있습니다.
children을 활용한 컴포넌트 재사용
children을 사용하면 컴포넌트가 내부에 어떤 내용을 표시할지를 부모 컴포넌트가 결정할 수 있게 됩니다. 예를 들어, 다음과 같이 Card라는 컴포넌트를 만들 수 있습니다.
import React from 'react';
function Card({ children }) {
return (
<div style={{ border: '1px solid #ccc', padding: '16px', borderRadius: '8px' }}>
{children}
</div>
);
}
export default Card;
이 Card 컴포넌트는 children을 받아서, 전달된 내용을 카드 형식으로 감싸서 출력합니다. 이제 이 컴포넌트를 다른 곳에서 사용할 때, 내부에 표시할 내용을 자유롭게 결정할 수 있습니다.
아래와 같이 Card 컴포넌트를 여러 가지 방식으로 재사용할 수 있습니다.
import React from 'react';
import Card from './Card';
function App() {
return (
<div>
<Card>
<h2>제목 1</h2>
<p>첫 번째 카드의 내용</p>
</Card>
<Card>
<h2>제목 2</h2>
<p>두 번째 카드의 내용</p>
<button>클릭</button>
</Card>
</div>
);
}
export default App;
동작원리
일반 자바스크립트에서는 DOM을 직접 조작합니다. 예를 들어, 상태가 변경되었을 때, 특정 요소를 찾아서 직접 수정하거나, 새로운 내용을 삽입하는 방식으로 작업을 진행합니다. 이 과정에서는 다음과 같은 단점이 있습니다:
- 복잡한 코드: 상태가 변경될 때마다 어떤 요소를 변경해야 하는지 직접 찾아서 수정해야 하기 때문에, 코드가 복잡해지고 유지보수가 어려워집니다.
- 비효율적인 업데이트: DOM 조작은 상대적으로 비용이 많이 드는 작업입니다. 상태 변경이 있을 때마다 DOM 전체를 재렌더링하거나, 불필요한 부분까지 다시 그리게 될 수 있습니다.
React는 이와 다르게 Virtual DOM을 사용합니다. React에서 상태(state)가 변경되면, React는 다음과 같은 방식으로 동작합니다:
- Virtual DOM 생성: 상태 변경에 따라 새로운 Virtual DOM을 생성합니다. Virtual DOM은 메모리 내에서 가상으로 유지되는 DOM의 복제본입니다.
- Diffing: React는 새로운 Virtual DOM과 이전 Virtual DOM을 비교하여, 변경된 부분을 찾습니다. 이 과정은 매우 효율적이며, 변경된 부분만 정확히 찾아냅니다.
- 최소한의 실제 DOM 업데이트: 실제 DOM에서 필요한 부분만 업데이트하여, 전체 DOM을 다시 그리지 않고도 UI를 최신 상태로 유지합니다.
이러한 방식 덕분에, React는 일반 자바스크립트와 비교했을 때 더 간단하고 효율적으로 상태 변화를 관리하고 UI를 업데이트할 수 있습니다. React의 Virtual DOM과 Reconciliation 알고리즘 덕분에, 성능이 최적화되고 불필요한 DOM 조작이 줄어들게 됩니다.
'React > 정리' 카테고리의 다른 글
리액트 전역 상태 관리: useContext 훅 (0) | 2024.08.12 |
---|---|
리액트 상태 관리: useReducer, useImmer 알아보기 (0) | 2024.08.12 |
useState, useEffect (0) | 2024.08.12 |
JSX 문법 (0) | 2024.08.11 |
Create React App (0) | 2024.08.11 |