프론트엔드

React 입문 가이드

지식소 채움이 2025. 5. 23. 14:44

React란 무엇인가 – 배경과 목적

React는 Facebook에서 개발한 자바스크립트 라이브러리로, 웹과 모바일 환경에서 빠르고 동적인 사용자 인터페이스를 구축할 수 있도록 도와줍니다. 2013년에 오픈소스로 공개되었으며, 컴포넌트와 가상 DOM(virtual DOM) 개념을 도입해 UI 업데이트를 효율화했습니다. 특히 React는 단일 페이지 애플리케이션(SPA) 개발을 간편하게 해 주며, 단방향 데이터 흐름과 선언적(UI 선언 방식) 설계를 통해 예측 가능하고 유지보수하기 쉬운 코드를 작성할 수 있게 합니다.

  • 컴포넌트 기반: UI를 재사용 가능한 작은 조각(컴포넌트)으로 분리합니다. 예를 들어 버튼, 입력창 같은 요소를 독립된 컴포넌트로 만들어 조합하여 전체 화면을 구성할 수 있습니다.
  • 가상 DOM: 실제 DOM 대신 메모리상의 가상 DOM에서 변경 사항을 먼저 계산하여, 필요한 부분만 효율적으로 갱신합니다. 이를 통해 성능 저하를 줄이고 빠른 화면 업데이트를 구현합니다.
  • 단방향 데이터 흐름: 데이터가 부모에서 자식 컴포넌트로만 흐르도록 설계되어, 데이터 변화 과정을 추적하기 쉽고 예측 가능한 상태 관리가 가능합니다.

React는 페이스북을 비롯해 많은 기업과 개발자 커뮤니티에서 널리 채택되고 있으며, 동적이고 반응성 높은 웹/앱 개발을 위한 핵심 도구로 자리잡고 있습니다.

React의 주요 개념 소개 – 컴포넌트, JSX, Props, State

React의 핵심 개념에는 컴포넌트, JSX, Props, State 등이 있습니다. 컴포넌트는 UI를 이루는 독립적인 구성 요소이며, JSX는 자바스크립트 코드 안에 HTML과 유사한 문법을 사용할 수 있게 해주는 문법 확장입니다. Props와 State는 컴포넌트에 데이터를 전달하고 관리하는 방식입니다. 이들 개념을 이해하면 React로 UI가 어떻게 구성되고 업데이트되는지 파악할 수 있습니다.

  • 컴포넌트 (Component): UI를 구성하는 재사용 가능한 독립 단위입니다. React는 *“UI를 개별 조각(컴포넌트)으로 만들어 결합”*하는 방식을 사용합니다. 각 컴포넌트는 자체 코드와 스타일을 가지며, 필요할 때 조합하여 전체 화면을 구성할 수 있습니다.
  • JSX: JavaScript에 HTML 태그 문법을 결합한 문법입니다. 일반 자바스크립트 코드 안에 <div>와 같은 마크업을 직접 작성할 수 있으며, 이를 통해 UI의 구조를 직관적으로 표현할 수 있습니다. 이 코드는 컴파일 과정에서 순수 자바스크립트로 변환되어 실행됩니다.
  • Props: 부모 컴포넌트가 자식 컴포넌트로 넘겨주는 읽기 전용 데이터입니다. 컴포넌트에 전달하는 속성(attributes)으로, 자식 컴포넌트는 props를 통해 전달된 값을 읽기만 할 수 있고 변경할 수 없습니다.
  • State: 컴포넌트 내부에서 선언하고 관리하는 변경 가능한 데이터입니다. 사용자 입력이나 네트워크 응답 등에 따라 State를 변경하면, 해당 컴포넌트가 자동으로 다시 렌더링되어 화면이 업데이트됩니다. useState Hook이나 클래스 컴포넌트의 this.state를 통해 다룰 수 있습니다.

간단한 예제 코드 – Hello World 컴포넌트

React를 처음 시작할 때 가장 기본이 되는 예제는 “Hello, World!”를 화면에 출력하는 컴포넌트입니다. 다음은 함수형 컴포넌트로 작성한 간단한 예제 코드입니다:

import React from 'react';

function App() {
  return (
    <div>
      <h1>Hello, World!</h1>
    </div>
  );
}

export default App;

위 코드에서 App은 React 함수형 컴포넌트로, JSX 문법을 사용해 <h1>Hello, World!</h1>를 반환합니다. 이 컴포넌트를 렌더링하면 화면에 “Hello, World!” 문구가 나타납니다. import React from 'react'로 React 기능을 가져오고, 마지막 줄의 export default App;로 외부에서 사용할 수 있도록 컴포넌트를 내보냅니다. GeeksforGeeks 문서에서도 이와 동일한 예제로 Hello, World! 컴포넌트를 소개하고 있습니다.

컴포넌트 구조 – 함수형 vs 클래스형 차이

React 컴포넌트는 두 가지 방식으로 정의할 수 있습니다: 함수형 컴포넌트와 클래스형 컴포넌트.

  • 함수형 컴포넌트: 간단한 자바스크립트 함수로 작성합니다. function MyComponent(props) { ... } 형태로 정의하고, 내부에서 props를 받아 JSX를 반환합니다. 상태 관리가 필요할 때는 React Hooks를 활용합니다. 예를 들면:
  • function Welcome(props) { return <h1>안녕하세요, {props.name}님!</h1>; }
  • 클래스형 컴포넌트: ES6 클래스로 작성하며 React.Component를 상속합니다. render() 메서드를 구현하여 JSX를 반환하며, 내부에서 this.props와 this.state를 사용할 수 있습니다. 예시:
  • class Welcome extends React.Component { render() { return <h1>안녕하세요, {this.props.name}님!</h1>; } }

과거에는 상태 관리나 라이프사이클 메서드를 위해 클래스형 컴포넌트가 많이 사용되었지만, React 16.8 이후 Hooks가 도입되면서 함수형 컴포넌트 중심으로 코드가 작성되는 추세입니다. 함수형 컴포넌트는 코드가 간결하고 이해하기 쉽다는 장점이 있습니다.

Props와 State의 개념과 차이

React에서 PropsState는 데이터 관리의 핵심 개념입니다. State는 컴포넌트 내부에서 관리되는 변경 가능한 데이터이며, Props는 부모 컴포넌트에서 전달받는 읽기 전용 데이터입니다.

  • Props: 부모로부터 전달되어 들어오는 값으로, 컴포넌트 간에 데이터를 주고받을 때 사용합니다. 읽기 전용이기 때문에 컴포넌트 내부에서 직접 변경할 수 없고, 부모가 새로운 props를 넘겨주면 자식 컴포넌트가 업데이트됩니다. 예를 들어 <Child name="React" />에서 Child 컴포넌트는 props.name으로 "React"를 받아 사용할 수 있습니다.
  • State: 컴포넌트 내부에서 선언하고 관리하는 데이터입니다. 사용자의 입력이나 네트워크 응답 등으로 변할 수 있으며, 상태가 변경되면 컴포넌트가 자동으로 다시 렌더링되어 UI가 업데이트됩니다. 클래스형 컴포넌트에서는 this.state와 this.setState로, 함수형 컴포넌트에서는 useState Hook으로 다룹니다.
  • 차이점: Props는 외부(부모)에서 주입된 읽기 전용 값이고, State는 내부에서 변경 가능한 값이라는 점이 가장 큰 차이입니다. 즉, Props는 컴포넌트의 입력값이라면, State는 컴포넌트의 자체 상태라고 볼 수 있습니다.

Props와 State를 적절히 활용하면, 상위 컴포넌트가 State를 관리하고 하위 컴포넌트에게 Props로 전달하여 UI를 구성하는 방식으로 구조를 짤 수 있습니다. 이 원칙을 통해 데이터의 흐름과 변경 과정을 명확히 할 수 있습니다.

이벤트 처리 방법

React에서 이벤트 처리 방식은 일반 DOM과 비슷하지만 약간의 문법 차이가 있습니다. 주요 특징은 이벤트 이름을 camelCase로 작성하고, JSX에서 함수 형태로 핸들러를 전달한다는 점입니다. 예를 들어 HTML의 <button onclick="doSomething()">는 React에서는 <button onClick={doSomething}>처럼 작성합니다.

다음은 버튼 클릭 이벤트를 처리하는 예제입니다:

function Clicker() {
  const handleClick = () => {
    console.log('버튼이 클릭되었습니다!');
  };
  return (
    <button onClick={handleClick}>
      클릭하세요
    </button>
  );
}

위 코드에서 handleClick 함수는 버튼이 클릭될 때 호출됩니다. React는 onClick={handleClick}처럼 함수를 넘겨받아 내부에서 호출하며, 추가로 이벤트 객체를 인자로 받을 수도 있습니다. 이렇게 하면 버튼을 눌렀을 때 콘솔에 메시지가 출력됩니다.

또한 onChange, onSubmit 등 다양한 이벤트를 사용할 수 있으며, JSX 안에서는 문자열이 아닌 함수를 전달해야 한다는 점에 주의합니다. 이벤트 처리 함수 안에서는 preventDefault()를 호출해 기본 동작을 막거나, State를 업데이트해 화면을 변경하는 등 동적 처리가 가능합니다.

React Hooks 소개 – useState, useEffect 기본 사용법

React 16.8 이후 도입된 Hooks를 사용하면 함수형 컴포넌트에서도 상태 관리와 라이프사이클 기능을 활용할 수 있습니다.

  • useState: 함수형 컴포넌트에 로컬 상태를 추가할 수 있도록 하는 Hook입니다. const [value, setValue] = useState(initialValue) 형태로 사용하며, value는 현재 상태값, setValue는 값을 갱신하는 함수입니다. 예를 들어 다음 코드는 버튼 클릭 시 카운터가 증가하는 예시입니다:위 예시에서 count는 상태 변수이며, 버튼을 누를 때마다 setCount를 호출해 값을 변경합니다. 이로 인해 컴포넌트가 다시 렌더링되어 화면의 숫자가 업데이트됩니다.
  • import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>숫자: {count}</p> <button onClick={() => setCount(count + 1)}> 증가 </button> </div> ); }
  • useEffect: 컴포넌트가 렌더링된 이후 특정 작업(사이드 이펙트)을 수행할 수 있게 해주는 Hook입니다. 주로 데이터 가져오기, 타이머 설정, 이벤트 등록 등의 부수 효과를 처리합니다. 예를 들어 다음 코드는 타이머를 설정하여 1초마다 경과 시간을 갱신합니다:useEffect의 두 번째 인자로 빈 배열 []을 주면, 컴포넌트가 처음 마운트될 때만 이펙트가 실행됩니다. 위 예제에서는 컴포넌트가 화면에 표시된 후 1초마다 seconds 상태를 증가시켜 화면에 경과 시간을 나타냅니다. Hooks를 사용하면 이처럼 클래스형 컴포넌트의 라이프사이클을 함수형 컴포넌트에서도 손쉽게 구현할 수 있습니다.
  • import React, { useState, useEffect } from 'react'; function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const interval = setInterval(() => { setSeconds(s => s + 1); }, 1000); return () => clearInterval(interval); }, []); return <p>경과된 시간: {seconds}s</p>; }

간단한 프로젝트 구성 예시 – 할 일 목록 앱

React의 개념들을 종합해서 간단한 할 일 목록(To-Do List) 앱을 구성해 볼 수 있습니다. 이 앱은 사용자가 할 일을 입력하면 목록에 추가되고, 추가된 할 일들을 화면에 표시해 주는 구조로 만들 수 있습니다. 예를 들어 최상위 TodoApp 컴포넌트를 만들어 그 안에서 할 일 목록을 **상태(state)**로 관리하고, 입력 필드와 추가 버튼, 목록 렌더링 부분을 구현할 수 있습니다.

import React, { useState } from 'react';

function TodoApp() {
  const [todos, setTodos] = useState([]);      // 할 일 목록 상태
  const [input, setInput] = useState("");      // 입력 필드 상태

  const addTodo = () => {
    if (!input) return;
    setTodos([...todos, input]);              // 새로운 할 일 추가
    setInput("");
  };

  return (
    <div>
      <input
        placeholder="할 일을 입력하세요"
        value={input}
        onChange={(e) => setInput(e.target.value)}
      />
      <button onClick={addTodo}>추가</button>
      <ul>
        {todos.map((todo, idx) => (
          <li key={idx}>{todo}</li>
        ))}
      </ul>
    </div>
  );
}

위 코드에서 todos 상태는 현재까지 추가된 할 일 목록을 저장합니다. 사용자가 입력 필드에 내용을 작성하면 onChange로 input 상태가 업데이트되며, 추가 버튼을 누르면 addTodo 함수가 실행되어 todos 배열에 새로운 항목이 추가됩니다. todos.map()을 사용해 각 할 일을 <li>로 렌더링하면 화면에 목록이 나타납니다. 이처럼 React에서는 컴포넌트를 적절히 분리하고 **상태(state)**와 Props를 활용하여 작은 규모의 앱을 구성할 수 있습니다. 위 예시를 확장하면, 개별 할 일을 삭제하거나 완료 처리를 하는 등의 기능도 쉽게 추가할 수 있습니다.

React를 사용하면 이와 같이 작은 컴포넌트들을 조합해서 할 일 목록 앱뿐만 아니라 다양한 인터랙티브 웹 애플리케이션을 만들 수 있습니다. 이 글에서 다룬 개념들을 바탕으로, 점차 프로젝트의 규모를 늘려가며 React 사용법을 익혀보세요.