← Back to list

react-i18next & i18next 둘의 관계

i18n 구현시 대표되는 framework인 i18next 생태계에 대해 분석해보자.

Nayounsang · 2026-01-14 12:09 · 0 claps · 5.9 min read
#i18n #i18next #react-i18next
Open on Medium ↗
Wiki topics: 🌐 · Web Development

react-i18next & i18next 둘의 관계

i18n 구현시 대표되는 framework인 i18next 생태계에 대해 분석해보자.

Why “react”?

i18next는, react와 독립돼 어느 생태계(ex vanillaJS)에서 동작하는 로직을 담고 있다. 따라서, react-i18next가 필요하다.

i18next 사용시, 다음과 같이 사용한다.

export const MyComponent = () => {
  const {t} = useTranslation();

  return <p>{t("hi")}</p>
}

왜 이 “훅"이 필요한 것일까?

  • 리액트 컴포넌트 트리와 호환되는 i18n 인스턴스
  const { i18n: i18nFromProps } = props;
  const { i18n: i18nFromContext, defaultNS: defaultNSFromContext } =
    useContext(I18nContext) || {};
  const i18n = i18nFromProps || i18nFromContext || getI18n();

기본적인 설정으론 geti18n() 를 통해 싱글톤인스턴스를 사용하나, context와 props(사실 hook이므로 params가 적당하겠다.)를 통해 i18n 인스턴스를 주입하는 것을 허용하기 위함이다.

  • 최적화
  const i18nOptions = useMemo(
    () => ({ ...getDefaults(), ...i18n?.options?.react, ...props }),
    [i18n, props],
  );

리액트 컴포넌트 생명주기상 발생하는 병목을 해소하기 위해 일부 로직에서 useCallback , useMemo 를 사용한다.

  • suspense 연동
  if (i18n && useSuspense && !ready) {
    throw new Promise((resolve) => {
      const onLoaded = () => resolve();
      if (props.lng) {
        loadLanguages(i18n, props.lng, namespaces, onLoaded);
      } else {
        loadNamespaces(i18n, namespaces, onLoaded);
      }
    });
  }

옵션에 따라 Promise를 throw하는 로직을 만들어 Suspense와 호환한다.

반대로, useSuspense를 disable했을 땐

  useEffect(() => {
    if (i18n && !ready && !useSuspense) {
      const onLoaded = () => setLoadCount((c) => c + 1);
      if (props.lng) {
        loadLanguages(i18n, props.lng, namespaces, onLoaded);
      } else {
        loadNamespaces(i18n, namespaces, onLoaded);
      }
    }
  }, [i18n, props.lng, namespaces, ready, useSuspense, loadCount]);

useEffect내에서 이를 처리해 loadLanguages(loadNamespaces)로직을 리액트 생명주기와 동기화한다.

  • i18next의 내부 상태를 react와 동기화

무엇보다, i18next는 react 밖의 로직이므로, 이를 react render cycle과 연동시켜야한다. useSyncExternalStore은 외부 store를 react 세계로 끌어온다.

const { t, ready } = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);

i18next의 역할에 대해선 추후 살펴보자.

  • 그 외

이외 많은 역할이 있으나, 내 이해력과 시간으로 인해 남겨두겠다. 소스코드는 여기서 확인할 수 있다.

Core Responsibilities

그럼, 코어 로직을 담는 i18next가 뭐하는 것일까?

  • use API를 통한 플러그인 연동
  use(module) {
    if (!module) throw new Error('You are passing an undefined module! Please check the object you are passing to i18next.use()')
    if (!module.type) throw new Error('You are passing a wrong module! Please check the object you are passing to i18next.use()')

    if (module.type === 'backend') {
      this.modules.backend = module;
    }

    if (module.type === 'logger' || (module.log && module.warn && module.error)) {
      this.modules.logger = module;
    }

    if (module.type === 'languageDetector') {
      this.modules.languageDetector = module;
    }

    if (module.type === 'i18nFormat') {
      this.modules.i18nFormat = module;
    }

    if (module.type === 'postProcessor') {
      postProcessor.addPostProcessor(module);
    }

    if (module.type === 'formatter') {
      this.modules.formatter = module;
    }

    if (module.type === '3rdParty') {
      this.modules.external.push(module);
    }

    return this;
  }
  • 인스턴스 초기화

설정 옵션으로 i18next 인스턴스를 초기화한다.

  • 리소스 관리
this.store = new ResourceStore(this.options.resources, this.options);

loadNamespaces, loadLanguages와 같은 API를 제공하고,

init 메서드의 option으로 설정한 resource를 ResourceStore에 등록한다.

  • 번역 인터페이스 제공

react와 독립적인 t, getFixedT function을 제공한다.

  • 이벤트

changeLanguages와 같은 이벤트 API를 제공한다.

  • 그외

[embed]API | i18next documentation i18next.init(options, callback) // -> returns a Promise The default export of the i18next module is an i18next instance…www.i18next.com

결론

  • i18n 로직 자체는 i18next의 API로 제공된다.
  • i18next는 내부 자체 스토어로 동작한다.
  • i18next의 로직과 스토어를 react 컴포넌트 트리 & 생명주기와 연동하며, 최적화를 할 필요가 존재해 react-i18next를 사용한다.

메타데이터
post_id
8dff2ec23943
slug
react-i18next-i18next-둘의-관계-8dff2ec23943
url
https://medium.com/@nayounsang722/react-i18next-i18next-%EB%91%98%EC%9D%98-%EA%B4%80%EA%B3%84-8dff2ec23943
canonical_url
https://medium.com/@nayounsang722/react-i18next-i18next-%EB%91%98%EC%9D%98-%EA%B4%80%EA%B3%84-8dff2ec23943
author_url
https://medium.com/@nayounsang722
status
ok
fetched_at
2026-07-11 17:44:30