
# React SDK

`@keenauth/react`는 삽입 가능한 로그인, 가입, 계정 컴포넌트와 그 아래에서 동작하는 훅을 제공합니다. 브라우저 코어인 [`@keenauth/js`](/docs/sdk/js) 위에서 동작하며, 모든 네트워크 호출, PKCE, DPoP, WebAuthn 절차는 코어가 처리합니다. 컴포넌트가 `fetch`나 WebCrypto를 직접 호출하지는 않습니다. 이 패키지는 아직 npm에 게시되지 않았습니다.

호스팅된 로그인 페이지로 리디렉션하는 방식으로 로그인하려면 이 패키지가 필요하지 않습니다. `@keenauth/js`를 직접 사용하는 [React 빠른 시작](/docs/quickstarts/react)을 참조하십시오.

## 프로바이더 설정

코어를 한 번 생성한 뒤 `KeenAuthProvider`에 전달하십시오. 컴포넌트가 서버 문제를 인식할 수 있도록 React 패키지의 오류 클래스를 코어에 전달하십시오.

```tsx
import { KeenAuth } from "@keenauth/js";
import { KeenAuthProblemError, KeenAuthProvider, SignIn } from "@keenauth/react";

const core = new KeenAuth({
  issuer: "https://acme.eu.keenauth.app",
  clientId: "app_01j9zzzzzzzzzzzzzzzzzzzz",
  redirectUri: "https://login.acme.example/callback",
  createProblemError: (problem) => new KeenAuthProblemError(problem),
});

export function App() {
  return (
    <KeenAuthProvider core={core} locale="en">
      <SignIn transaction={{ client_id: "app_01j9zzzzzzzzzzzzzzzzzzzz", redirect_uri: "https://login.acme.example/callback" }} />
    </KeenAuthProvider>
  );
}
```

`KeenAuthProvider`는 다음 속성을 받습니다.

| 속성 | 의미 |
|---|---|
| `core` | `@keenauth/js` 클라이언트(`KeenAuthCore` 계약을 구현한 모든 객체) |
| `locale` | UI 언어(BCP 47), 기본값 `en` |
| `appearance` | 선택 사항인 테마 재정의, [외관](#외관) 참조 |

컴포넌트는 환경의 쿠키와 CSRF 헤더를 사용해 프론트 API(`/fapi/v1`)를 호출합니다. 서버는 이러한 호출을 해당 환경의 로그인 출처에서만, 그리고 자사 애플리케이션에 대해서만 허용합니다.

## 컴포넌트

| 컴포넌트 | 기능 |
|---|---|
| `SignIn` | 식별자 우선 로그인: 비밀번호, 패스키, 이메일 코드 또는 매직 링크, 두 번째 인증 요소 |
| `SignUp` | 환경의 등록 설정에 따른 가입 |
| `UserProfile` | 로그인한 사용자의 프로필, 이메일(인증 코드 확인 포함), 패스키 및 세션 |

`SignIn`과 `SignUp`은 로그인 트랜잭션을 시작하는 본문인 `transaction`을 받습니다.

- 리디렉션 방식에서는 인증 요청의 `{ authorization_request: "azr_…" }`를 사용합니다.
- 리디렉션이 없는 경우에는 등록된 리디렉션 URI와 함께 `{ client_id, redirect_uri }`를 사용합니다.

`onComplete`는 코어가 페이지 안에서 트랜잭션을 마치면 호출됩니다. 리디렉션 방식에서는 대신 페이지가 다른 곳으로 이동합니다. 컴포넌트가 직접 그리지 않는 단계(예: 챌린지 또는 조직 선택)는 호스팅된 로그인 페이지에서 계속 진행할 수 있는 링크가 됩니다.

`UserProfile`은 `profile`, `emails`, `passkeys`, `sessions`의 부분 집합인 `sections`를 받습니다(기본값은 네 가지 모두). 다른 곳에서 이루어진 변경과 충돌하는 프로필 쓰기는 오류를 표시하고 현재 값을 다시 불러옵니다.

## 훅

| 훅 | 반환 값 |
|---|---|
| `useKeenAuth()` | 프로바이더 값: `core`, `locale`, `appearance` |
| `useEnvironment()` | 환경의 로그인 설정과 활성 로케일용 텍스트 조회 함수 `t` |
| `useTransaction()` | 코어의 `transactions` API 위에서 동작하는 트랜잭션 상태 머신 |
| `useMe()` | 로그인한 사용자의 프로필과 계정 API |

## 외관

`appearance.variables`는 테마 토큰(예: `color.primary`)을 재정의합니다. 이 값은 CSSOM을 통해 컴포넌트 루트에 `--idp-*` 사용자 정의 속성으로 기록되므로, `'unsafe-inline'` 스타일을 허용하지 않는 엄격한 Content Security Policy에서도 동작합니다. `appearance.elements`는 컴포넌트 요소에 사용자의 클래스 이름을 추가합니다. 이 패키지는 스타일시트를 포함하지 않으므로, `idp-*` 클래스는 직접 작성한 CSS에서 스타일을 지정하십시오.

```tsx
<KeenAuthProvider core={core} appearance={{ variables: { "color.primary": "#1f6feb" }, elements: { buttonPrimary: "acme-button" } }}>
```

## 언어와 접근성

- 컴포넌트에는 영어, 터키어, 프랑스어, 독일어, 한국어, 일본어, 이탈리아어, 스페인어 텍스트가 포함되어 있습니다. 환경의 텍스트 재정의가 먼저 적용되며, 그 밖의 로케일은 영어로 대체되고 해당 로케일의 텍스트 방향을 따릅니다.
- 모든 입력 필드에는 레이블이 있고, 오류 요약이 포커스를 받으며, `autocomplete` 값이 설정되고, 붙여넣기는 절대 차단하지 않습니다.

## 패스키

패스키 버튼은 패스키의 Relying Party ID가 페이지의 호스트를 포함할 때(또는 페이지의 출처가 환경의 관련 출처인 경우) 나타납니다. 그렇지 않으면 컴포넌트가 호스팅된 로그인 페이지로 연결되는 링크를 표시합니다. 패스키는 보안 컨텍스트(`https` 또는 `localhost`)가 필요합니다.

## 현재 제한 사항

- 소셜 로그인 버튼은 아직 그려지지 않습니다. 소셜 로그인을 제공하는 환경에서는 호스팅된 로그인 페이지로 연결되는 링크가 표시됩니다.
- 전화번호는 아직 사용할 수 없습니다. `UserProfile`에는 전화번호 섹션이 없습니다.
- 조직 컴포넌트(조직 전환기와 프로필)는 아직 사용할 수 없습니다.
