# Host Integration URL: /lynx/getting-started/host-integration Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/getting-started/host-integration.mdx 호스트 앱이 주는 색상 스킴·모션 설정·safe area를 SeedProvider로 SEED에 전달하는 방법을 알아봅니다. ## 개요 Lynx의 global props는 Lynx가 정의하지 않는 값이고, 어떤 키가 들어오는지는 호스트 앱마다 다릅니다. SEED는 특정 호스트의 global props 키를 직접 읽지 않고, 앱이 `SeedProvider`로 넘긴 값만 사용합니다. 어떤 키를 읽어 어떻게 바꿀지는 앱이 정합니다. | prop | 타입 | 사용하는 곳 | 생략했을 때 | | ---------------------- | -------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------ | | `preferredColorScheme` | `"light" \| "dark"` | `useSeedClassName`의 `colorMode: "system"`, 아이콘 색상 동기화 | `"light"` | | `preferredMotion` | `"default" \| "reduced"` | [Scale Feedback](/lynx/components/concepts/scale-feedback). `"reduced"`이면 눌림 축소를 끕니다 | `"default"` | | `safeAreaInsets` | `{ top, right, bottom, left }` (논리 px) | `useSafeArea`, `Box`의 `"safeArea"`, AppBar, Dialog, MenuSheet, floating 레이어 경계 | `env(safe-area-inset-*)` | 화면 크기는 넘기지 않습니다. SEED는 [`useViewport`](/lynx/hooks/use-viewport)로 현재 LynxView 크기를 직접 측정합니다. `preferredColorScheme`은 호스트가 선호하는 값입니다. root `colorMode`를 적용한 결과가 아니므로, `colorMode: "dark-only"`인 앱에서도 호스트 설정을 그대로 넘기세요. ## 적용하기 앱 root에 `SeedProvider`를 하나 두고, 호스트의 global props를 SEED 값으로 바꿔 넘깁니다. global props는 `pluginReactLynx`의 [`globalPropsMode`](/lynx/getting-started/feature-flags)에 맞게 읽습니다. 기본값 `"reactive"`에서는 호스트가 값을 바꾸면 페이지 전체가 다시 렌더되므로 `lynx.__globalProps`를 바로 읽고, `"event"`에서는 `useGlobalProps()`로 읽어 변경을 구독합니다. ```tsx title="src/index.tsx" import { root } from "@lynx-js/react"; import { SeedProvider, useSeedClassName, type SafeAreaInsets } from "@seed-design/lynx-react"; // 호스트 계약은 앱이 선언합니다. interface HostGlobalProps { theme?: string; motion?: string; safeAreaInsetTop?: number; safeAreaInsetRight?: number; safeAreaInsetBottom?: number; safeAreaInsetLeft?: number; } function Page() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } const isValidInset = (value: unknown): value is number => typeof value === "number" && Number.isFinite(value) && value >= 0; function toSafeAreaInsets(g: HostGlobalProps): SafeAreaInsets | undefined { const { safeAreaInsetTop: top, safeAreaInsetRight: right } = g; const { safeAreaInsetBottom: bottom, safeAreaInsetLeft: left } = g; // 4방향 모두 0 이상의 유한한 숫자일 때만 넘깁니다. if (!isValidInset(top) || !isValidInset(right) || !isValidInset(bottom) || !isValidInset(left)) { return undefined; } return { top, right, bottom, left }; } function Root() { // globalPropsMode: "event"이면 `useGlobalProps() as HostGlobalProps`로 읽습니다. const g = lynx.__globalProps as HostGlobalProps; return ( ); } root.render(); ``` `useSeedClassName`은 `SeedProvider` 안에서 호출해야 `preferredColorScheme`을 읽습니다. 위 예제처럼 ``를 그리는 컴포넌트를 Provider 안쪽에 둡니다. `SeedProvider`가 없어도 오류는 나지 않습니다. 호스트 값이 없는 환경에서는 위 표의 "생략했을 때" 값으로 동작합니다. ### Safe Area 값 `safeAreaInsets`는 4방향을 모두 넘깁니다. SEED는 받은 값을 보정하지 않고 그대로 `px`로 쓰므로, 음수나 `NaN` 같은 값은 위 예제처럼 앱에서 걸러 주세요. `0`도 유효한 값이므로, 네이티브가 이미 여백을 확보했다면 `0`을 넘기세요. `safeAreaInsets`를 생략하면 `env(safe-area-inset-*)`를 씁니다. Android에서는 이 CSS 함수가 동작하지 않아 safe area가 `0`처럼 보일 수 있으니, 호스트가 값을 주지 않는 경우의 보정도 앱에서 정하세요. ### Overlay 안에서 다른 Safe Area 쓰기 같은 Lynx View의 ``는 global props를 공유합니다. fullscreen과 overlay에 다른 safe area가 필요하면 overlay 콘텐츠 안에 `SafeAreaProvider`를 중첩합니다. 그 영역의 `useSafeArea()`와 `useSeedContext().safeAreaInsets`가 함께 바뀝니다. ```tsx import { SafeAreaProvider } from "@seed-design/lynx-react"; ; ``` `SeedProvider`를 중첩하면 생략한 prop은 바깥 Provider의 값을 이어받습니다. ## 넘긴 값 읽기 `useSeedContext()`는 `SeedProvider`가 받은 값을 그대로 돌려줍니다. px 문자열 변환이나 `env()` fallback은 하지 않습니다. 화면에 적용할 safe area 값이 필요하면 [`useSafeArea`](/lynx/hooks/use-safe-area)를 사용하세요. ```tsx import { useSeedContext } from "@seed-design/lynx-react"; const { preferredColorScheme, preferredMotion, safeAreaInsets } = useSeedContext(); ``` ## Global Props 직접 읽기 이전 버전의 SEED는 당근 앱 호스트가 넣어 주는 global props(`theme`, `motion`, `safeAreaInset*`)를 직접 읽었습니다. 기존 앱이 바로 깨지지 않도록 다음 메이저 버전 전까지는 `SeedProvider`에 넘기지 않은 값만 이 키에서 채웁니다. - 키가 실제로 있어 사용되면 개발 빌드에서 키마다 한 번 경고합니다. 키가 없는 호스트에서는 경고하지 않습니다. - `safeAreaInsets`를 생략하면 `useSafeArea`가 `safeAreaInset*` global props를 읽고, 값이 없으면 `env(safe-area-inset-*)`를 씁니다. - 이 경로는 다음 메이저 버전에서 제거될 예정입니다. 위 [적용하기](#적용하기)처럼 `SeedProvider`로 옮기세요.