React 컴포넌트와 Hook 핵심 요약 정리

김덕진·2025년 6월 7일

React

목록 보기
2/13

✅ React 컴포넌트와 주요 Hook 정리

🔹 컴포넌트 만드는 법 (React의 기본)

  1. 함수형 컴포넌트 정의

    function MyComponent() {
      return <div>Hello!</div>;
    }

    또는

    const MyComponent = () => {
      return <div>Hello!</div>;
    };

    React에선 함수형 컴포넌트를 더 많이 씁니다. 화살표 함수도 가능합니다.

  2. 컴포넌트는 <MyComponent />처럼 사용

    • 반드시 대문자 시작이어야 React가 컴포넌트로 인식합니다.
  3. 불필요한 <div> 대신 <></> 사용 가능

    return (
      <>
        <Header />
        <Content />
      </>
    );

    <></>React.Fragment의 축약형입니다. DOM 구조가 깔끔해집니다.

  4. 컴포넌트는 순수 함수(Pure Function)처럼 동작해야 합니다.

    같은 props가 들어가면 항상 같은 결과를 반환해야 해요.

📦 주의

  • A 컴포넌트의 state는 B 컴포넌트에서 직접 사용할 수 없습니다. 예:

    const Parent = () => {
      const [count, setCount] = useState(0);
      return <Child />; // count 전달 안 됨
    };

    상태 공유가 필요하다면 props, context, redux 등을 사용해야 합니다.


🔹 useEffect: React의 생명주기 대응 Hook

useEffect(() => {
  console.log("마운트 시 실행");
}, []);

[]를 전달하면 마운트될 때 한 번만 실행됩니다.

🧠 실행 타이밍 이해하기:

  • Render Phase: 컴포넌트 함수 실행 (useEffect는 실행 안됨)
  • Commit Phase: 실제 DOM 적용 (이 시점 이후에 useEffect 실행)
  • Paint Phase: 브라우저가 화면 그리기 완료

📦 주의

  • DOM이 완전히 업데이트된 뒤에 실행되므로, DOM 조작보다는 비동기 요청 등에 적합합니다.

🔹 useMemo & useCallback

Hook반환값사용 목적예시
useMemo계산된 값무거운 계산 결과 재사용const value = useMemo(() => calc(a), [a])
useCallback함수동일한 함수 객체 유지const onClick = useCallback(() => doSomething(), [deps])

📦 주의

  • useMemo는 값 메모이제이션, useCallback은 함수 메모이제이션입니다.
  • 과도하게 쓰면 오히려 성능이 떨어질 수 있으니 꼭 필요한 경우만 사용하세요.

🔹 useRef: DOM 접근 및 값 저장

const inputRef = useRef(null);

const handleFocus = () => {
  inputRef.current.focus();
};

return <input ref={inputRef} />;

📌 설명

  • useRefDOM에 직접 접근하거나, 렌더링에 영향을 주지 않는 값 저장에 적합합니다.
  • 값이 바뀌어도 컴포넌트는 리렌더링되지 않습니다.

🔹 useReducer vs useState

const reducer = (state, action) => {
  switch (action.type) {
    case "increment": return { count: state.count + 1 };
    case "decrement": return { count: state.count - 1 };
    default: throw new Error("Unknown action");
  }
};
const [state, dispatch] = useReducer(reducer, { count: 0 });

🆚 비교표

항목useReduceruseState
목적복잡한 상태 로직단순 상태
구조reducer 함수로 처리직접 setState
적합한 상황여러 상태 묶기단일 값 처리

📦 주의

  • reducer 함수는 action에 따라 상태를 어떻게 변경할지를 명확하게 정의해야 합니다.

🔹 useContext: 전역 데이터 공유

const MyContext = React.createContext();
const value = useContext(MyContext);

🆚 비교

항목PropsuseContext
구조부모 → 자식 단방향어디서든 접근 가능
성능변경된 부분만 렌더연결된 컴포넌트 모두 렌더링

📦 주의

  • Context 값이 바뀌면 모든 자식 컴포넌트가 다시 렌더링됩니다.

🔹 useLayoutEffect vs useEffect

단계useLayoutEffectuseEffect
실행 시점DOM 적용 직후, 화면 그리기 전화면 그린 후
적합한 작업DOM 조작, 스타일 측정비동기 요청, 상태 처리
깜빡임 방지

📦 주의

  • useLayoutEffect는 동기적으로 실행되므로 UI가 멈출 수 있습니다. DOM 조작 용도로만 사용하세요.

🔹 Custom Hook: 공통 로직 재사용

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return width;
}

📌 설명

  • 여러 Hook (useState, useEffect, 등)을 조합해 복잡한 로직을 공통화할 수 있습니다.

🔹 Hook 사용 규칙 (매우 중요)

  1. 무조건 최상위 레벨에서 호출할 것

    if (condition) {
      useEffect(() => {}, []); // ❌ 이렇게 하면 안됨
    }

    매 렌더링마다 Hook 호출 순서가 달라지면 React 내부 상태가 꼬입니다.

  2. React 함수 컴포넌트나 Custom Hook 안에서만 호출할 것

    일반 함수나 조건문, 루프에서는 절대 호출하지 마세요.


🔹 기타 패턴 요약

  • 조건부 렌더링: isVisible && <Component /> 또는 삼항 연산자 condition ? A : B

  • 리스트 렌더링: map() 사용 + 고유한 key 필요

  • select 박스: value 바인딩 필요, 다중 선택은 multiple={true} + 배열

    <select value={selectedValue} onChange={handleChange}>
      <option value="a">A</option>
    </select>
  • 이벤트 핸들러 기본 구조

    const handleChange = (event) => {
      setValue(event.target.value);
    };

📌 event 구조 요약

  • event: 이벤트 객체
  • event.target: 이벤트 발생 요소
  • event.target.value: 해당 요소의 value 값

🔹 Context 사용 시 주의: value에 함수형 값 전달하기

const MyContext = createContext();

const Parent = () => {
  const contextValue = { message: "Hello" };

  return (
    <MyContext.Provider value={contextValue}>
      <Child />
    </MyContext.Provider>
  );
};

📦 주의

  • value에 객체, 배열, 함수 리터럴 등 매번 새로 생성되는 값을 전달하면 Provider가 매 렌더링마다 새로운 참조를 전달하게 되어, 모든 하위 컴포넌트가 리렌더링됩니다.

✅ 해결 방법:

const contextValue = useMemo(() => ({ message: "Hello" }), []);

useMemo를 이용해 참조값을 유지하면 불필요한 리렌더링을 방지할 수 있습니다.


🔹 BrowserRouter: 라우팅의 기본

import { BrowserRouter, Routes, Route } from "react-router-dom";

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/about" element={<About />} />
  </Routes>
</BrowserRouter>

📌 설명

  • BrowserRouter는 HTML5 History API를 활용해 페이지 전체 새로고침 없이 URL을 변경해주는 컴포넌트입니다.
  • 보통 앱의 최상단에 위치시킵니다.

🔹 Suspense & Spinner: 지연 로딩 처리

import { lazy, Suspense } from "react";
import LoadingSpinner from "./LoadingSpinner";

const OtherComponent = lazy(() => import("./OtherComponent"));

function MyComponent() {
  return (
    <Suspense fallback={<LoadingSpinner />}>
      <OtherComponent />
    </Suspense>
  );
}

📌 설명

  • Suspense는 lazy 로딩된 컴포넌트가 로드되기 전까지 대기 상태를 표시합니다.
  • fallback에 로딩 컴포넌트(예: Spinner)를 지정해 사용자 경험을 개선합니다.

📦 주의

  • Suspenselazy()와 함께 사용할 때만 동작합니다.
  • 서버 사이드 렌더링(SSR)에서는 별도 설정이 필요합니다.

항목Link 방식useNavigate 방식
사용 방식정적 이동 (클릭 기반)동적 이동 (로직 기반)
예시메뉴, 리스트 항목 등조건 분기, API 후 이동
URL 변경사용자가 클릭해야 발생함수 호출로 발생
뒤로 가기 지원❌ (Link 자체로는 불가능)✅ (navigate(-1))

추천 사용처

  • 사용자 UI에서 직접 클릭해 이동 → Link
  • 로직 흐름 속에서 이동 제어 필요 시 → useNavigate()
// Link 사용
<Link to="/home">Home</Link>

// useNavigate 사용
const navigate = useNavigate();
navigate("/home");

📦 주의

  • useNavigate()react-router-dom의 훅이며, 컴포넌트 내에서만 호출 가능합니다.
profile
FrontEnd Developer

0개의 댓글