@ngsk2784-lab/core
v0.1.0
Published
Framework/platform-agnostic client-side logic shared across ngsk2784-lab apps (auth session, http wrapper, validation, utils, storage adapters). See docs/architecture.md.
Readme
@ngsk2784-lab/core
공유 클라이언트 로직 라이브러리. 웹·데스크탑·모바일·웹게임 전 플랫폼에서 코드를 재사용하려는 목적으로, 프레임워크·플랫폼 무관 TypeScript로 작성된 순수 로직을 제공합니다.
대상: login-hub 생태계에 속한 모든 컨슈머 앱 (React/Next, React Native, Electron, Phaser 등)
설치
npm install @ngsk2784-lab/coreOptional Peer Dependencies
모듈에 따라 선택적 peer를 설치하세요:
# @core/auth 사용
npm install login-hub-sdk
# @core/api 사용
npm install ky
# @core/validation 사용
npm install zod
# React Native storage adapter 사용
npm install @react-native-async-storage/async-storage빠른 시작 (공개 클라이언트 PKCE 로그인)
1. 세션 초기화
import { createAuthSession, createStorage } from '@ngsk2784-lab/core';
import { webStorage } from '@ngsk2784-lab/core/storage/web';
const auth = createAuthSession({
config: {
clientId: process.env.CLIENT_ID,
hubUrl: process.env.HUB_URL,
},
storage: webStorage,
});2. 로그인 URL 생성 & 리다이렉트
const loginUrl = await auth.createLoginUrl(
'https://myapp.example.com/auth/callback'
);
window.location.href = loginUrl;3. 콜백 라우트에서 code 교환
const searchParams = new URLSearchParams(window.location.search);
const code = searchParams.get('code');
const state = searchParams.get('state');
try {
const session = await auth.exchange(code, 'https://myapp.example.com/auth/callback', state);
console.log('로그인 성공:', session.user.nickname);
} catch (error) {
console.error('로그인 실패:', error.message);
}4. API 호출 시 토큰 자동 주입
import { createApiClient } from '@ngsk2784-lab/core/api';
const api = createApiClient({
baseUrl: 'https://api.example.com',
getAccessToken: async () => {
const token = await auth.getAccessToken();
return token;
},
onAuthFailure: () => {
// 재로그인 필요
window.location.href = '/login';
},
});
// Authorization 헤더는 자동으로 붙습니다
const data = await api.get('me').json();모듈 가이드
@core/auth — 세션 매니저
공개 클라이언트(PKCE) OAUTH2 로그인 흐름을 구현합니다. 토큰은 클라이언트가 직접 보유하며, 주입된 StorageAdapter에 저장됩니다.
API: createAuthSession(options) → AuthSession
const auth = createAuthSession({
config: {
clientId: 'YOUR_CLIENT_ID',
hubUrl: 'https://login.example.com',
},
storage: webStorage, // 아래의 storage adapters 참고
refreshTokenStorage: 'persistent', // 기본값. 'memory'로 설정하면 페이지 새로고침 후 재로그인 필요
});
// PKCE 리다이렉트 흐름
const loginUrl = await auth.createLoginUrl(redirectUri);
const session = await auth.exchange(code, redirectUri, state);
const token = await auth.getAccessToken(); // 만료 시 자동 refresh
await auth.logout();주의사항 (웹 SPA):
login-hub-sdk/next를 사용하면 (httpOnly 쿠키, BFF 모델) 이 패키지는 불필요합니다.- 순수 SPA에서 이 패키지를 사용한다면,
refreshTokenStorage: 'memory'로 설정 권장 (XSS 위험 감소). 단, 페이지 새로고침 후 토큰이 지워지므로 재로그인이 필요합니다.
@core/api — HTTP 클라이언트
ky 기반 HTTP 래퍼. 자동 401 refreshe, 타임아웃, 에러 정규화를 제공합니다.
API: createApiClient(options) → KyInstance
import { createApiClient } from '@ngsk2784-lab/core/api';
const api = createApiClient({
baseUrl: 'https://api.example.com',
timeoutMs: 15000,
getAccessToken: async () => {
const session = await auth.getSession();
return session?.accessToken ?? null;
},
onRefresh: async () => {
// 토큰 refresh 로직. true 반환하면 원래 요청을 재시도합니다
const refreshed = await auth.getAccessToken();
return !!refreshed;
},
onAuthFailure: () => {
// 재로그인 필요
window.location.href = '/login';
},
});
// ky 인스턴스처럼 사용
const data = await api.get('users/me').json();@core/storage/* — Storage 어댑터
토큰/세션 저장 위치를 선택합니다.
웹 (localStorage / sessionStorage)
import { webStorage } from '@ngsk2784-lab/core/storage/web';
const auth = createAuthSession({
config: { /* ... */ },
storage: webStorage,
});인메모리 (테스트, SSR, 단기 수명)
import { memoryStorage } from '@ngsk2784-lab/core/storage/memory';
const auth = createAuthSession({
config: { /* ... */ },
storage: memoryStorage,
});React Native (AsyncStorage)
import { rnStorage } from '@ngsk2784-lab/core/storage/rn';
const auth = createAuthSession({
config: { /* ... */ },
storage: rnStorage,
});@core/validation — 검증 스키마
zod 기반 공통 필드 스키마 + safeValidate 래퍼.
제공 스키마:
emailSchema— RFC 형식 이메일passwordSchema— 8~72자, 영문+숫자 필수koreanPhoneSchema— 010-XXXX-XXXX (자동 정규화)nicknameSchema— 2~20자, 한글/영문/숫자/언더스코어/하이픈
import { safeValidate, emailSchema, nicknameSchema } from '@ngsk2784-lab/core/validation';
const result = safeValidate(emailSchema, userInput);
if (!result.success) {
console.error(result.error.message);
console.error(result.error.issues); // [{ path: string, message: string }, ...]
}@core/utils — 환경변수 & 유틸
환경변수 정규화 헬퍼.
import { required, optional, clean } from '@ngsk2784-lab/core/utils';
const apiUrl = required(process.env.API_URL, 'API_URL');
const timeout = optional(process.env.TIMEOUT_MS, '10000');
// clean(): 따옴표·공백 제거 (Infisical/Railway 주입값 처리)
const key = clean(process.env.SECRET_KEY);비-JS 플랫폼 (Godot / Unity)
core는 JavaScript만 지원합니다. Godot(GDScript)이나 Unity(C#)는 login-hub HTTP 프로토콜을 직접 구현해야 합니다.
자세한 내용은 login-hub/docs/api-contract.md를 참고하세요.
필요한 엔드포인트:
GET /authorize— 로그인 시작 (PKCE code_challenge 필수)POST /token— code 교환 (code_verifier 필수)POST /token(grant_type=refresh_token) — 토큰 갱신POST /logout— 로그아웃GET /.well-known/jwks.json— 토큰 검증용 공개키
구조
@ngsk2784-lab/core
├── ./auth 세션 매니저 (login-hub-sdk 래핑)
├── ./api HTTP 클라이언트 래퍼 (ky)
├── ./validation zod 스키마 + safeValidate
├── ./utils env 헬퍼
├── ./storage/web localStorage 어댑터
├── ./storage/memory 인메모리 어댑터
├── ./storage/rn AsyncStorage 어댑터 (React Native)
└── . 공통 타입 (User, Session, ApiError) + 배럴각 모듈은 독립적으로 tree-shake됩니다. 쓰는 것만 번들에 포함됩니다.
API 참고
AuthSession 메서드
| 메서드 | 반환값 | 설명 |
|--------|--------|------|
| createLoginUrl(redirectUri) | Promise<string> | 로그인 URL 생성 (state + PKCE 자동 저장) |
| exchange(code, redirectUri, state) | Promise<Session> | authorization code 교환 (CSRF 검증 포함) |
| getAccessToken() | Promise<string \| null> | 현재 access token (만료 시 자동 refresh) |
| getSession() | Promise<Session \| null> | 현재 세션 (claims + user) |
| logout() | Promise<void> | 로그아웃 (허브 revoke + 로컬 스토리지 정리) |
Session 타입
{
accessToken: string; // JWT, 15분 만료
refreshToken: string; // opaque, 30일 만료
claims: {
sub: string; // user ID
exp: number; // 만료 timestamp (sec)
email: string | null;
nickname: string;
avatarUrl: string | null;
provider: 'google' | 'naver' | 'kakao';
};
user: {
id: string;
provider: 'google' | 'naver' | 'kakao';
email: string | null;
nickname: string;
avatarUrl: string | null;
};
}라이선스
MIT — docs/architecture.md 참고
문서 & 설계: docs/architecture.md
login-hub API 계약: login-hub/docs/api-contract.md
GitHub: https://github.com/ngsk2784-lab/core
