Sdk Design PatternsSAFE
Overview
An agent skill published by revfactory.
459e1bb8f76eOBSERVED · 2026-10-12What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: sdk-design-patterns
description: "SDK/API 클라이언트 설계 패턴: 빌더 패턴, 인터셉터 체인, 재시도 전략, 타입 안전 설계, 에러 핸들링, 페이지네이션 래퍼 가이드. 'SDK 설계', '클라이언트 패턴', '재시도 전략', '인터셉터', '빌더 패턴', 'SDK 에러 처리', '타입 안전', 'SDK 아키텍처' 등 SDK 구조 설계 시 이 스킬을 사용한다. sdk-developer의 SDK 설계 역량을 강화한다. 단, API 스펙 파싱이나 테스트/문서 작성은 이 스킬의 범위가 아니다."
---
# SDK Design Patterns — SDK 설계 패턴 가이드
타입 안전하고 사용하기 쉬운 API 클라이언트 SDK를 설계하는 패턴 카탈로그.
## SDK 아키텍처
```
┌─────────────────────────────────────────┐
│ SDK Public API │
│ client.users.list() │
│ client.orders.create({...}) │
├─────────────────────────────────────────┤
│ Resource Clients │
│ UsersClient, OrdersClient, ... │
├─────────────────────────────────────────┤
│ Middleware Chain │
│ Auth → Retry → RateLimit → Logger │
├─────────────────────────────────────────┤
│ HTTP Transport │
│ fetch / axios / httpx │
└─────────────────────────────────────────┘
```
## 빌더 패턴 (Client 초기화)
### TypeScript
```typescript
const client = new ApiClient({
baseUrl: 'https://api.example.com',
apiKey: process.env.API_KEY,
timeout: 30000,
retries: 3,
// 선택적 커스텀
fetch: customFetch,
headers: { 'X-Custom': 'value' },
});
// 리소스 접근
const users = await client.users.list({ page: 1, perPage: 20 });
const user = await client.users.get('user_123');
const newUser = await client.users.create({ name: '홍길동', email: '[email protected]' });
```
### Python
```python
client = ApiClient(
base_url="https://api.example.com",
api_key=os.environ["API_KEY"],
timeout=30.0,
max_retries=3,
)
# Context Manager 지원
async with ApiClient(api_key="...") as client:
users = await client.users.list(page=1, per_page=20)
```
## 인터셉터/미들웨어 체인
```typescript
// 인터셉터 인터페이스
interface Interceptor {
beforeRequest(config: RequestConfig): Promise<RequestConfig>;
afterResponse(response: Response): Promise<Response>;
onError(error: Error): Promise<never>;
}
// 인증 인터셉터
class AuthInterceptor implements Interceptor {
async beforeRequest(config) {
config.headers['Authorization'] = `Bearer ${this.token}`;
return config;
}
async onError(error) {
if (error.status === 401 && this.refreshToken) {
await this.refresh();
return this.retry(error.config);
}
throw error;
}
}
// 재시도 인터셉터
class RetryInterceptor implements Interceptor {
async onError(error) {
if (this.shouldRetry(error) && this.attempt < this.maxRetries) {
await this.backoff(this.attempt);
return this.retry(error.config);
}
throw error;
}
}
```
## 재시도 전략
```typescript
class RetryStrategy {
private maxRetries = 3;
private baseDelay = 1000; // ms
shouldRetry(error: ApiError): boolean {
// 재시도 가능한 에러만
return [408, 429, 500, 502, 503, 504].includes(error.status);
}
getDelay(attempt: number, error: ApiError): number {
// 429: Retry-After 헤더 우선
if (error.status === 429 && error.headers['retry-after']) {
return parseInt(error.headers['retry-after']) * 1000;
}
// 지수 백오프 + 지터
const exponential = this.baseDelay * Math.pow(2, attempt);
const jitter = Math.random() * this.baseDelay;
return Math.min(exponential + jitter, 60000); // 최대 60초
}
}
```
## 타입 안전 설계
### TypeScript 제네릭 활용
```typescript
// 리소스 타입 정의
interface User {
id: string;
name: string;
email: string;
createdAt: Date;
}
interface CreateUserRequest {
name: string;
email: string;
}
interface ListUsersParams {
page?: number;
perPage?: number;
sort?: 'name' | 'createdAt';
order?: 'asc' | 'desc';
}
// 제네릭 리소스 클라이언트
class ResourceClient<T, CreateT, UpdateT, ListParams> {
async list(params?: ListParams): Promise<PaginatedResponse<T>> { ... }
async get(id: string): Promise<T> { ... }
async create(data: CreateT): Promise<T> { ... }
async update(id: string, data: UpdateT): Promise<T> { ... }
async delete(id: string): Promise<void> { ... }
}
// 구체적 클라이언트
class UsersClient extends ResourceClient<User, CreateUserRequest, UpdateUserRequest, ListUsersParams> {
// 추가 메서드
async listOrders(userId: string): Promise<Order[]> { ... }
}
```
### Python Pydantic 모델
```python
from pydantic import BaseModel, Field
from datetime import datetime
class User(BaseModel):
id: str
name: str
email: str
created_at: datetime = Field(alias="createdAt")
class Config:
populate_by_name = True
class CreateUserRequest(BaseModel):
name: str
email: str
```
## 페이지네이션 래퍼
```typescript
// 자동 페이지 순회
class PaginatedResponse<T> {
data: T[];
hasMore: boolean;
nextCursor?: string;
// 이터레이터 지원
async *[Symbol.asyncIterator](): AsyncIterator<T> {
let response: PaginatedResponse<T> = this;
while (true) {
for (const item of response.data) {
yield item;
}
if (!response.hasMore) break;
response = await this.fetchNext(response.nextCursor);
}
}
}
// 사용법
for await (const user of client.users.list()) {
console.log(user.name); // 모든 페이지를 자동 순회
}
// 특정 페이지만
const page1 = await client.users.list({ perPage: 20 });
```
## 에러 핸들링
```typescript
// 에러 계층 구조
class ApiError extends Error {
status: number;
code: string;
details?: any;
}
class BadRequestError extends ApiError { status = 400; }
class AuthenticationError extends ApiError { status = 401; }
class NotFoundError extends ApiError { status = 404; }
class RateLimitError extends ApiError {
status = 429;
retryAfter: number;
}
class InternalError extends ApiError { status = 500; }
// 사용
try {
const user = await client.users.get('invalid_id');
} catch (e) {
if (e instanceof NotFoundError) {
console.log('사용자를 찾을 수 없습니다');
} else if (e instanceof RateLimitError) {
console.log(`${e.retryAfter}초 후 재시도하세요`);
}
}
```
## SDK 품질 체크리스트
```markdown
### 사용성
- [ ] 3줄 이내로 시작 가능 (Quick Start)
- [ ] IDE 자동완성 100% 지원 (타입 완전)
- [ ] 에러 메시지가 해결 방법을 안내
- [ ] 동기/비동기 모두 지원
### 견고성
- [ ] Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | NA |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
459e1bb8f76efull audit observations/trust-audit/skill/revfactory__sdk-design-patterns.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-12 | 459e1bb8f76e | SAFE | B | 89 | first audit |
Questions
Is Sdk Design Patterns safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Sdk Design Patterns access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
How current is this page?
The grade is for one exact copy of the source (459e1bb8f76e), read on 2026-10-12. The repository is watched, and a new audit runs when it changes — this is the first audit.