누구나 로고
Online CoursesFor BusinessLibraryTrend InsightsFree coursesNoticesContactCareers
모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.
로그인무료 회원가입
강좌리액트 입문 — 컴포넌트로 만드는 웹16강

16강 / 전체 28강

커스텀 훅 만들기

5분 읽기 조회 0

Context API로 Props drilling 없이 전역 상태를 공유하는 방법, Provider 패턴 설계, 그리고 Context 남용을 피하는 기준을 배웁니다.

🌐 Props Drilling — 전달 피로

컴포넌트 트리가 깊어지면 Props Drilling이 발생합니다. 최상위 컴포넌트의 데이터가 최하위까지 닿으려면 중간에 있는 모든 컴포넌트가 Props를 전달해야 합니다. 중간 컴포넌트들은 그 데이터를 실제로 쓰지도 않으면서 전달만 하게 됩니다.

// ❌ Props Drilling
function App() {
  const [user, setUser] = useState<User | null>(null)
  return <Layout user={user} />       // Layout은 user를 쓰지 않지만 전달해야 함
}
function Layout({ user }: { user: User | null }) {
  return <Header user={user} />       // Header도 마찬가지
}
function Header({ user }: { user: User | null }) {
  return <UserMenu user={user} />     // 실제로 쓰는 곳은 여기뿐
}
function UserMenu({ user }: { user: User | null }) {
  return <span>{user?.name}</span>    // 여기서 비로소 사용
}

이것이 Context API가 해결하려는 문제입니다.

⚙️ Context 만들기 — 3단계

Context 설정은 세 단계입니다: ① Context 생성 → ② Provider로 공급 → ③ useContext로 소비.

// contexts/AuthContext.tsx
import { createContext, useContext, useState, ReactNode } from 'react'

interface User {
  id: string
  name: string
  email: string
}

interface AuthContextType {
  user: User | null
  login: (user: User) => void
  logout: () => void
}

// ① Context 생성
const AuthContext = createContext<AuthContextType | null>(null)

// ② Provider 컴포넌트
export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null)

  const login = (user: User) => setUser(user)
  const logout = () => setUser(null)

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  )
}

// ③ 소비 훅 (선택이지만 권장)
export function useAuth(): AuthContextType {
  const context = useContext(AuthContext)
  if (!context) throw new Error('useAuth는 AuthProvider 안에서 사용해야 합니다')
  return context
}

🔌 Provider 등록과 사용

// main.tsx 또는 App.tsx에서 Provider로 감싸기
import { AuthProvider } from './contexts/AuthContext'

function App() {
  return (
    <AuthProvider>
      <Layout />  {/* 아래 모든 컴포넌트에서 useAuth() 사용 가능 */}
    </AuthProvider>
  )
}

// 어디서든 바로 사용 — Props 없이!
function UserMenu() {
  const { user, logout } = useAuth()

  if (!user) return null
  return (
    <div className="flex items-center gap-3">
      <span className="text-sm font-medium">{user.name}</span>
      <button onClick={logout} className="text-sm text-gray-500 hover:text-red-500">
        로그아웃
      </button>
    </div>
  )
}

🎨 여러 Context 조합하기

실제 앱에서는 여러 Context를 함께 씁니다. 각 Context는 하나의 관심사에 집중합니다:

// ContextProviders.tsx — 모든 Provider를 한 곳에서 합성
function ContextProviders({ children }: { children: ReactNode }) {
  return (
    <AuthProvider>
      <ThemeProvider>
        <LanguageProvider>
          {children}
        </LanguageProvider>
      </ThemeProvider>
    </AuthProvider>
  )
}

// App.tsx에서 단 하나만 등록
function App() {
  return (
    <ContextProviders>
      <Layout />
    </ContextProviders>
  )
}

⚠️ Context 남용 금지 — 언제 쓰고 언제 피할까

Context가 적합한 경우Context가 과한 경우
인증 정보 (user, token)컴포넌트 1-2개만 사용하는 상태
테마 (dark/light)자주 바뀌는 상태 (성능 문제)
언어/지역 설정form 상태 (로컬로 충분)
전역 알림/토스트부모-자식 1단계 차이

Context value가 바뀌면 해당 Context를 소비하는 모든 컴포넌트가 리렌더링됩니다. 자주 변하는 상태(마우스 위치, 스크롤 등)를 Context에 넣으면 성능 문제가 생깁니다. 그런 경우에는 Zustand 같은 외부 상태 관리 라이브러리를 고려하세요.

✅ 정리

  • Context API: Props Drilling 없이 컴포넌트 트리 어디서든 데이터를 공유합니다.
  • 단계: createContext → Provider로 감싸기 → useContext로 소비.
  • 커스텀 훅(useAuth)으로 Context 접근을 캡슐화하면 가독성이 좋아집니다.
  • 인증·테마·언어처럼 넓은 범위에서 쓰이는 데이터에만 사용하세요.

관련 주제

  • use 접두사 규칙
  • 커스텀 훅 설계
  • 반복 로직 추출
  • useToggle 예시
  • 개발·프로그래밍
  • 개발·프로그래밍 강의
  • 리액트 입문 — 컴포넌트로 만드는 웹
  • 무료강의
  • 무료 온라인 강의
  • NUGUNA
  • 누구나
이전 15강useRef와 DOM 접근다음 17강 Context API

댓글

0/1000

불러오는 중...

목차

  1. 1.리액트란 무엇인가
  2. 2.개발 환경 만들기 — Vite
  3. 3.JSX 기초
  4. 4.컴포넌트 만들기
  5. 5.Props로 데이터 전달
  6. 6.State와 useState
  7. 7.이벤트 처리
  8. 8.조건부 렌더링
  9. 9.리스트 렌더링과 key
  10. 10.폼 다루기
  11. 11.useEffect 기초
  12. 12.데이터 가져오기(fetch)
  13. 13.상태 끌어올리기
  14. 14.컴포넌트 합성과 재사용
  15. 15.useRef와 DOM 접근
  16. 16.커스텀 훅 만들기
  17. 17.Context API
  18. 18.useReducer
  19. 19.리스트 앱 실전 ①
  20. 20.리스트 앱 실전 ②
  21. 21.라우팅 — React Router
  22. 22.스타일링 방법들
  23. 23.리스트·상세 페이지 연결
  24. 24.비동기 상태 관리 패턴
  25. 25.성능 기초 — memo
  26. 26.에러 처리와 경계
  27. 27.환경변수와 빌드
  28. 28.배포하기

Support

  • Notices
  • FAQ
  • Contact Us
  • Community

Help & Info

  • Terms of Service
  • Privacy Policy
  • Refund Policy

Services

  • About Us
  • Sign up
  • New courses
  • Free courses
누구나 로고
Terms of ServicePrivacy PolicyRefund Policy

상호명: NUGUNA  |  대표자: 정우진  |  사업자등록번호: 392-32-01817  |  통신판매업신고: 제 2026-서울양천-0564 호

주소: 서울특별시 양천구 목동서로 100  |  이메일: nugunapass@gmail.com  |  전화: 010-6395-3043

© 2026 NUGUNA. All rights reserved.

KB예금주인증관리자
HomeCoursesLibraryContactMY