dev/react

React 필수 기초 개념

두구둥둥 2025. 6. 29. 18:30

React란?

  • UI(사용자 인터페이스)를 만들기 위한 JavaScript 라이브러리
  • 컴포넌트 기반으로 UI를 쪼개서 재사용 가능 
  • 단방향 데이터 흐름 지향
  • SPA(Single Page Application) 구현에 주로 사용

컴포넌트란?

  • UI를 독립적이고 재사용 가능한 단위로 나눈 것

 

  • 함수형 컴포넌트 (권장)
  • 클래스형 컴포넌트 (이전 버전에서 사용, 지금은 거의 함수형만 씀)

예시 - 함수형 컴포넌트

function Hello() {
  return <h1>Hello, React!</h1>;
}

 

SPA(Single Page Application)란?

  • 말그대로 해석하면 한개의 페이지로 구성된 웹 애플리케이션 
  • 처음 페이지 로드시 필요한 HTML, CSS, JS를 모두 받아옴 -> 초기 로딩 느림
  • 이후에는 페이지 전환 시 새로고침 없이 필요한 부분만 동적으로 랜더링 -> 빠름
  • 즉, 서버에 매번 요청해서 전체 페이지를 가져오는 방식이 아님
장점 단점
부드러운 화면 전환 초기 로딩 시간이 상대적으로 길 수 있음
모바일 앱 느낌의 자연스러운 UX SEO(검색 최적화) 어려움 -> Next.js로 해결 가능
서버 부담 감소 JS의존도가 높음 -> 코드 관리 중요

단방향 데이터 흐름 (One-way Data Binding)

  • React에서는 데이터가 위->아래, 부모->자식 방향으로만 흐르는 구조를 가진다.
  • 데이터 흐름 예측이 가능함
  • 디버깅과 유지보수가 쉬움

예시1 - Parent -> Child 방향으로만 데이터 흐름 : message 는 Parent가 소유

function Parent() {
  const [message, setMessage] = useState("안녕하세요");

  return <Child msg={message} />;
}

function Child({ msg }) {
  return <h1>{msg}</h1>;
}

 

예시2 - Chilld -> Parent 방향으로 데이터 전달 : 콜백 함수를 prop로 전달

function Parent() {
  const [text, setText] = useState("");

  const handleChange = (value) => {
    setText(value);
  };

  return <Child onChange={handleChange} />;
}

function Child({ onChange }) {
  return (
    <input 
      onChange={(e) => onChange(e.target.value)} 
      placeholder="입력하세요" 
    />
  );
}

JSX란? (JavaScript XML)

  • JavaScript 코드 안에 HTML을 작성할 수 있는 문법
  • 일반적으로 JS코드 안에서 HTML처럼 작성
const element = <h1>Hello, JSX!</h1>;
  • 실제로는 JavaScript 객체로 변환됨
const element = React.createElement('h1', null, 'Hello, JSX!');

 

JSX 사용시 주의사항

  • 태그는 꼭 닫아야 한다.
<img src="image.jpg" />
<br /> 
<br> //오류발생
  • 최상위 태그는 하나만 있어야 한다
// 오류 발생
return (
  <h1>Title</h1>
  <p>내용</p>
);

// 올바른 방식
return (
  <div>
    <h1>Title</h1>
    <p>내용</p>
  </div>
);

// Fragment 사용 가능
return (
  <>
    <h1>Title</h1>
    <p>내용</p>
  </>
);
  • JavaScript 표현식 사용 가능
const name = "홍길동";
return <h1>Hello, {name}!</h1>;

return <p>{1 + 2} 입니다</p>;
  • class는 JS예약어라 JSX에서는 className 사용
return <div className="container">내용</div>;
  • 인라인 스타일은 객체 형태로 작성
const style = {
  color: "red",
  fontSize: "20px"
};

return <h1 style={style}>스타일 적용</h1>;

예시 

function Greeting({ name }) {
  return (
    <div>
      <h1>안녕하세요, {name}님!</h1>
      <p>오늘도 좋은 하루 되세요.</p>
    </div>
  );
}

//사용
<Greeting name="철수" />

 JSX 장점

  • HTML, JS를 한 파일에서 관리 -> 가독성, 생산성 향상
  • 동적인 UI를 쉽게 작성

예시 - JSX없이 작성

const element = React.createElement('h1', { className: 'title' }, 'Hello');

예시 - JSX

const element = <h1 className="title">Hello</h1>;

 

🎯JSX 실습 예제

1단계: 가장 기본적인 JSX 작성

<h1> 태그로 "안녕하세요, React!"라는 글씨를 출력하는 JSX 코드를 작성하세요.

function HelloReact() {
  return <h1>안녕하세요, React!</h1>;
}

2단계: 변수 활용

name이라는 변수에 "홍길동"을 저장하고,
"안녕하세요, 홍길동님!"을 출력하는 JSX 코드를 작성하세요.

function HelloHong({ name }) {
  return <h1>안녕하세요, {name}님!</h1>;
}

// 사용 예시
<HelloHong name="홍길동" />;

3단계: 여러 요소 묶어서 반환

다음 2개의 요소를 JSX로 반환하세요:

  • <h1> 태그로 "제목입니다"
  • <p> 태그로 "내용입니다"

단, 올바르게 하나의 부모로 감싸야 합니다.

function Blog() {
  return (
    <div>
      <h1>제목입니다</h1>
      <p>내용입니다</p>
    </div>
  );
}

4단계: 동적 표현

숫자 변수 num1 = 5, num2 = 10이 있을 때,
<p> 태그로 "합계: 15"를 출력하는 JSX 코드를 작성하세요.

function SumNumber() {
  const num1 = 5;
  const num2 = 10;
  return <p>합계: {num1 + num2}</p>;
}

5단계: 조건부 렌더링

isLoggedIn이라는 불리언 변수가 있을 때,

  • true면 <h1>환영합니다!</h1>
  • false면 <h1>로그인 해주세요.</h1>

를 출력하는 JSX 코드를 작성하세요.
삼항 연산자(조건 ? 참 : 거짓) 사용하기

function Greeting({ isLoggedIn }) {
  return <h1>{isLoggedIn ? "환영합니다!" : "로그인 해주세요."}</h1>;
}

// 사용 예시
<Greeting isLoggedIn={true} />;

6단계: 리스트 렌더링

다음 배열을 JSX로 <ul> 리스트로 출력하세요:

js
복사편집
const fruits = ["사과", "바나나", "딸기"];

각 아이템은 <li>로 감싸고, 반드시 key 속성을 사용하세요.

function FruitList() {
  const fruits = ["사과", "바나나", "딸기"];

  return (
    <ul>
      {fruits.map((fruit, index) => (
        <li key={index}>{fruit}</li>
      ))}
    </ul>
  );
}

State (상태)

  • 컴포넌트 내부에서 관리하는 데이터로 변경 가능함
  • useState 훅을 주로 사용
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // useState은 count: 상태값, setCount: 변경 함수 반환

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>증가</button>
    </div>
  );
}

State 특징

  • state가 바뀌면 해당 컴포넌트가 자동 재렌더링
  • 직접 변수에 값을 대입해도 UI는 바뀌지 않음 → 반드시 set함수 사용
  • state는 컴포넌트마다 독립적
  • state는 비동기로 처리될 수 있음 (즉시 반영되는 것처럼 보이지만 내부적으로는 batching 처리)

State 주의할 점

  • state는 직접 수정 금지 -> 불변성 유지
  • setState 호출 후 바로 변경된 값에 의존하면 안됨. -> 비동기적 특성 때문
  • 여러개의 state를 컴포넌트 내에서 자유롭게 사용 가능

예시

// 문자열 상태
const [text, setText] = useState("초기값");
<input value={text} onChange={(e) => setText(e.target.value)} />

// boolean 상태
const [isVisible, setIsVisible] = useState(false);
<button onClick={() => setIsVisible(!isVisible)}>보이기/숨기기</button>
{isVisible && <p>내용입니다.</p>}

// 배열 상태
const [items, setItems] = useState([]);
<button onClick={() => setItems([...items, "새 아이템"])}>추가</button>

// 객체 상태
const [user, setUser] = useState({ name: "홍길동", age: 20 });
<button onClick={() => setUser({ ...user, age: user.age + 1 })}>나이 증가</button>

언제 state를 써야 할까?

 

  • 화면에 출력되는 값이 바뀌는 경우
  • 사용자 입력을 반영할 때
  • 서버에서 데이터를 받아서 표시할 때
  • 토글, 카운터, 리스트 등 UI 상태 관리 필요할 때

🎯 State 실습 문제

✅ 1단계: 숫자 상태 만들기

숫자 상태를 0으로 초기화
버튼 클릭 시 숫자가 1씩 증가
현재 숫자를 <p> 태그로 표시

import { useState } from "react";

function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <div>
      <button onClick={() => setNumber(number + 1)}>증가</button>
      <p>{number}</p>
    </div>
  );
}

✅ 2단계: 문자열 상태 만들기

문자열 상태를 "초기값"으로 설정
<input>을 만들어 입력값을 상태로 반영
현재 입력값을 실시간으로 <p>에 출력

import { useState } from "react";

function TextState() {
  const [text, setText] = useState("초기값");

  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <p>{text}</p>
    </div>
  );
}

✅ 3단계: 불리언 상태 (토글)

true/false 상태 만들기
버튼 클릭 시 상태를 반전
상태가 true면 "ON", false면 "OFF"를 화면에 출력

import { useState } from "react";

function ToggleVisible() {
  const [visible, setVisible] = useState(true);

  return (
    <div>
      <button onClick={() => setVisible(!visible)}>토글버튼</button>
      {visible ? <p>ON</p> : <p>OFF</p>}
    </div>
  );
}

✅ 4단계: 배열 상태로 목록 추가

빈 배열 상태 생성
버튼 클릭 시 "새 아이템"을 배열에 추가
배열을 <ul>로 렌더링, 각 항목은 <li>로 출력

import { useState } from "react";

function AddList() {
  const [items, setItems] = useState([]);

  return (
    <div>
      <button onClick={() => setItems([...items, "새 아이템"])}>아이템 추가</button>
      <ul> 
        {items.map((item, index) => ( // 배열은 map으로 랜더링한다. for 사용불가. 고유한 key 필수
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

✅ 5단계: 객체 상태 수정

{ name: "홍길동", age: 20 } 상태 만들기
버튼 클릭 시 age가 1씩 증가
이름과 나이를 화면에 표시

import { useState } from "react";

function UserInfo() {
  const [user, setUser] = useState({ name: "홍길동", age: 20 });

  return (
    <div>
      <h2>{user.name}</h2>
      <p>나이: {user.age}</p>
      <button onClick={() => setUser({ ...user, age: user.age + 1 })}>나이 증가</button>
    </div>
  );
}