Files
2nd/10_Wiki/Topics/Frontend/백엔드-프론트엔드 데이터 변환(Data Transformation between Backend and Frontend).md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

6.3 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-백엔드-프론트엔드-데이터-변환-data-transforma 백엔드-프론트엔드 데이터 변환(Data Transformation between Backend and Frontend) 10_Wiki/Topics verified self
DTO
Data Transformation
API 응답 변환
snake_case to camelCase
none A 0.9 applied
frontend
backend
api
data-modeling
typescript
2026-05-10 pending
language framework
typescript react

백엔드-프론트엔드 데이터 변환(Data Transformation between Backend and Frontend)

매 한 줄

"매 server payload 매 client model 의 일치 안함 — adapter 의 boundary". 매 DB schema (snake_case, nullable, denormalized) 매 UI model (camelCase, optional, normalized)의 mismatch 의 explicit 의 mapping. 매 2026 의 Zod + tRPC + GraphQL codegen 의 type-safe automation.

매 핵심

매 mismatch dimensions

  • Naming: user_name (snake) ↔ userName (camel).
  • Types: 1693497600 (Unix epoch) ↔ Date object, "2026-05-10"Date.
  • Shape: nested vs flat, {user: {profile: {...}}}{userId, userName, ...}.
  • Nullability: null (DB) ↔ undefined (TS optional).
  • Enums: 0/1/2'pending' | 'active' | 'closed'.

매 layers (Clean Architecture)

  • DTO (Data Transfer Object) — wire format, snake_case, raw.
  • Domain Model — business rules, computed props.
  • View Model — UI-specific (formatted strings, derived flags).

매 응용

  1. REST API 의 camelCase 변환.
  2. GraphQL → TypeScript codegen.
  3. Date/Decimal 의 typed objects 변환.
  4. Form 의 server payload 의 transform.

💻 패턴

1. snake_case ↔ camelCase (humps library)

import { camelizeKeys, decamelizeKeys } from 'humps';

const apiResponse = { user_name: 'Alice', created_at: '2026-05-10' };
const camel = camelizeKeys(apiResponse) as { userName: string; createdAt: string };
// → { userName: 'Alice', createdAt: '2026-05-10' }

const payload = decamelizeKeys({ userName: 'Bob' });
// → { user_name: 'Bob' }

2. Zod schema (validate + transform)

import { z } from 'zod';

const UserDTO = z.object({
  user_id: z.number(),
  user_name: z.string(),
  created_at: z.string(),
  is_active: z.union([z.literal(0), z.literal(1)]),
}).transform(d => ({
  userId: d.user_id,
  userName: d.user_name,
  createdAt: new Date(d.created_at),
  isActive: d.is_active === 1,
}));

type User = z.infer<typeof UserDTO>;
// { userId: number; userName: string; createdAt: Date; isActive: boolean }

async function fetchUser(id: number): Promise<User> {
  const res = await fetch(`/api/users/${id}`);
  const json = await res.json();
  return UserDTO.parse(json); // validates + transforms
}

3. TanStack Query select (boundary transform)

import { useQuery } from '@tanstack/react-query';

export function useUser(id: number) {
  return useQuery({
    queryKey: ['user', id],
    queryFn: async () => {
      const res = await fetch(`/api/users/${id}`);
      return res.json();
    },
    select: (data) => UserDTO.parse(data), // transform per render
  });
}

4. Date / Decimal serialization

// server JSON cannot carry Date/BigInt natively
import Decimal from 'decimal.js';

const PaymentDTO = z.object({
  amount: z.string().transform(s => new Decimal(s)),
  paid_at: z.string().datetime().transform(s => new Date(s)),
});

// reverse: outgoing
function toPayload(p: { amount: Decimal; paidAt: Date }) {
  return {
    amount: p.amount.toString(),
    paid_at: p.paidAt.toISOString(),
  };
}

5. tRPC (no transform needed — type-safe RPC)

// server (router.ts)
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();

export const appRouter = t.router({
  user: t.procedure
    .input(z.object({ id: z.number() }))
    .query(async ({ input }) => {
      const u = await db.user.findUnique({ where: { id: input.id } });
      return u; // typed end-to-end
    }),
});

// client — types inferred, no manual mapping
const { data } = trpc.user.useQuery({ id: 1 });

6. GraphQL Codegen

# codegen.yml
schema: http://localhost:4000/graphql
documents: 'src/**/*.graphql'
generates:
  src/gql/types.ts:
    plugins:
      - typescript
      - typescript-operations
      - typescript-react-query

7. View Model layer (UI formatting)

type User = { firstName: string; lastName: string; createdAt: Date };
type UserVM = { fullName: string; joinedAgo: string };

function toVM(u: User): UserVM {
  return {
    fullName: `${u.firstName} ${u.lastName}`,
    joinedAgo: formatDistanceToNow(u.createdAt, { addSuffix: true }),
  };
}

매 결정 기준

상황 Approach
REST + TypeScript Zod schema 의 validate + transform at boundary.
Full-stack TypeScript monorepo tRPC 의 zero transform overhead.
GraphQL backend GraphQL Codegen 의 auto types.
Legacy snake_case API humps 의 camelize at fetch boundary.
BigInt / Decimal string serialization + parse on client.

기본값: Zod schema 의 boundary validation + transform. tRPC 매 monorepo 의 ideal.

🔗 Graph

🤖 LLM 활용

언제: API integration, form submission, type-safe full-stack, validation at trust boundary. 언제 X: 매 internal tool 의 untyped — 매 still validate 매 trust boundary.

안티패턴

  • Trust the API blindly: validate 매 trust boundary — server bug, version mismatch breaks UI silently.
  • Transform 의 component-level: scatter mapping logic — centralize at fetch layer.
  • any types: defeats TS — Zod infer 의 type derivation.
  • Date as string in app code: lose type safety — parse to Date at boundary.
  • Manual mapping 의 100 fields: codegen 의 use.

🧪 검증 / 중복

  • Verified (Zod docs, tRPC docs, Martin Fowler "Patterns of Enterprise Application Architecture").
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — full content with Zod/tRPC/Codegen patterns