Store는 전역, Context는 트리 범위 — 이 차이를 알면 언제 뭘 써야 할지 명확해집니다.

개념 정의

Context API 는 부모 컴포넌트가 자손 컴포넌트에게 명시적인 prop 전달 없이 데이터를 공유하는 메커니즘입니다. React의 Context API와 같은 개념이며, setContext로 설정하고 getContext로 가져옵니다.

기본 사용법

SVELTE
<!-- Parent.svelte -->
<script>
  import { setContext } from 'svelte';
  import Child from './Child.svelte';

  // 키와 값을 지정하여 컨텍스트 설정
  setContext('theme', {
    primary: '#ff3e00',
    secondary: '#676778',
    mode: 'light',
  });
</script>

<Child />
SVELTE
<!-- Child.svelte (또는 더 깊은 자손) -->
<script>
  import { getContext } from 'svelte';

  // 같은 키로 컨텍스트 가져오기
  const theme = getContext('theme');
</script>

<div style:color={theme.primary}>
  테마 색상이 적용됩니다
</div>

hasContext — 컨텍스트 존재 확인

SVELTE
<script>
  import { getContext, hasContext } from 'svelte';

  // 컨텍스트가 있는지 확인
  const hasTheme = hasContext('theme');
  const theme = hasTheme ? getContext('theme') : { primary: '#333' };
</script>

타입 안전한 Context

TYPESCRIPT
// context.ts — 컨텍스트 키와 타입을 중앙 관리
import { setContext, getContext } from 'svelte';

interface ThemeContext {
  primary: string;
  secondary: string;
  mode: 'light' | 'dark';
}

const THEME_KEY = Symbol('theme');

export function setThemeContext(theme: ThemeContext) {
  setContext(THEME_KEY, theme);
}

export function getThemeContext(): ThemeContext {
  return getContext<ThemeContext>(THEME_KEY);
}
SVELTE
<!-- Provider.svelte -->
<script>
  import { setThemeContext } from './context';

  setThemeContext({
    primary: '#ff3e00',
    secondary: '#676778',
    mode: 'light',
  });
</script>

<slot />
SVELTE
<!-- Consumer.svelte -->
<script>
  import { getThemeContext } from './context';

  const theme = getThemeContext();
  // TypeScript가 theme의 타입을 알고 있음!
</script>

반응형 Context

기본 Context 값은 반응형이 아닙니다. 반응형으로 만들려면 $state를 사용합니다.

SVELTE
<!-- ThemeProvider.svelte -->
<script>
  import { setContext } from 'svelte';

  let mode = $state('light');

  // $state 객체를 컨텍스트로 전달하면 반응형!
  setContext('theme', {
    get mode() { return mode; },
    toggle() { mode = mode === 'light' ? 'dark' : 'light'; },
  });
</script>

{@render children()}
SVELTE
<!-- DeepChild.svelte -->
<script>
  import { getContext } from 'svelte';

  const theme = getContext('theme');
</script>

<p>현재 모드: {theme.mode}</p>
<button onclick={theme.toggle}>테마 전환</button>

Store + Context 조합

Store를 Context에 넣으면 트리 범위의 반응형 상태를 깔끔하게 구현할 수 있습니다.

JAVASCRIPT
// cartContext.js
import { writable } from 'svelte/store';
import { setContext, getContext } from 'svelte';

const CART_KEY = Symbol('cart');

export function createCartContext() {
  const cart = writable([]);

  const context = {
    cart,
    addItem(item) {
      cart.update(items => [...items, item]);
    },
    removeItem(id) {
      cart.update(items => items.filter(i => i.id !== id));
    },
    get total() {
      let t = 0;
      cart.subscribe(items => {
        t = items.reduce((sum, i) => sum + i.price, 0);
      })();
      return t;
    },
  };

  setContext(CART_KEY, context);
  return context;
}

export function getCartContext() {
  return getContext(CART_KEY);
}

Context vs Store vs Props

특성PropsContextStore
범위부모→자식 직접컴포넌트 트리전역
반응성자동수동 설정 필요자동
인스턴스N/A트리별 독립싱글턴
용도직접 연결된 컴포넌트테마, 로케일 등 트리 범위인증, 전역 설정

**핵심 차이 **: Store는 앱 전체에서 하나의 인스턴스를 공유합니다. Context는 같은 컴포넌트가 다른 트리에 있으면 다른 Context 값을 받을 수 있습니다.

SVELTE
<!-- 같은 컴포넌트가 다른 Context를 받는 예시 -->
<script>
  import ThemeProvider from './ThemeProvider.svelte';
  import Card from './Card.svelte';
</script>

<ThemeProvider theme="light">
  <Card />  <!-- 라이트 테마 -->
</ThemeProvider>

<ThemeProvider theme="dark">
  <Card />  <!-- 다크 테마 — 같은 Card지만 다른 테마 -->
</ThemeProvider>

면접 포인트

  • "Context가 Store보다 나은 경우는?": 같은 컴포넌트를 다른 설정으로 여러 번 사용해야 할 때입니다. 예를 들어 하나의 페이지에 라이트 테마 섹션과 다크 테마 섹션이 공존하는 경우, Store는 전역이라 구분할 수 없지만 Context는 트리별로 다른 값을 제공합니다.
  • "setContext는 어디서 호출해야 하나요?": 컴포넌트 초기화 시점에만 호출 가능합니다. onMount 안이나 이벤트 핸들러에서는 호출할 수 없습니다.

정리

Context API는 "이 트리 아래에서는 이 데이터를 쓰겠다"를 선언하는 도구입니다. Props는 직접 연결, Store는 전역, Context는 트리 범위 — 세 가지 데이터 공유 방식을 상황에 맞게 고르면 깔끔한 아키텍처가 나옵니다.

댓글 로딩 중...