Files
2nd/10_Wiki/Topics/AI_and_ML/Client-Server Architecture Pattern.md
T
koriweb d8a80f6272 chore(wiki): dangling 링크 canonical 정규화 (768파일/1200건)
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해
끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은
과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업.
도구: Datacollect/scripts/link_reconcile_apply.mjs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:24:15 +09:00

8.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-client-server Client-Server Architecture Pattern 10_Wiki/Topics verified self
client-server
REST
gRPC
HTTP
web architecture
centralized model
two-tier
three-tier
none A 0.95 applied
architecture
client-server
rest
grpc
http
network
web-development
scalability
2026-05-10 pending
language framework
language-agnostic HTTP / REST / gRPC / WebSocket

Client-Server Architecture

📌 한 줄 통찰

"매 자원 의 request ↔ provider". 매 dominant network model. 매 single point of failure 가, 매 scale + control 의 huge. 매 modern: 매 BFF, 매 edge, 매 multi-region, 매 P2P 와 의 hybrid.

매 핵심

매 components

  • Client: 매 UI + 매 request.
  • Server: 매 logic + 매 data.
  • Network protocol: HTTP, gRPC, WebSocket, MQTT.

매 tier

  • Two-tier: client + DB.
  • Three-tier: client + app server + DB.
  • N-tier: client + BFF + microservices + DB + cache.

매 protocol comparison

Protocol Use case Latency Streaming
REST/HTTP General CRUD mid
gRPC Internal RPC low ✓ (bidirectional)
GraphQL Flexible query mid partial (subscription)
WebSocket Real-time very low
Server-Sent Events Server → Client low ✓ (one-way)
MQTT IoT, low-bandwidth low
WebRTC P2P media very low

매 advantages

  • 매 centralized control.
  • 매 division of labor.
  • 매 independent update.
  • 매 scale (server-side).
  • 매 strong security (server-side).

매 disadvantages

  • 매 single point of failure.
  • 매 network dependency.
  • 매 latency.
  • 매 cost (server infra).
  • 매 scaling complexity.

매 alternative / hybrid

  • P2P (BitTorrent, IPFS): 매 decentralized.
  • Edge computing: 매 close to user.
  • Serverless: 매 ephemeral.
  • CRDT + 매 sync: 매 offline-first.
  • Local-first (Ink & Switch).

매 modern pattern

BFF (Backend for Frontend)

  • 매 mobile / web 별 API.
  • 매 client-specific aggregation.

API Gateway

  • 매 single entry.
  • 매 auth / rate / route.

Service Mesh

  • 매 inter-service communication.
  • 매 Istio, Linkerd.

CDN / Edge

  • 매 static content.
  • 매 closer to user.
  • 매 Cloudflare Workers, Vercel Edge.

Multi-region

  • 매 active-active.
  • 매 latency 의 minimize.

💻 패턴

REST API (Express)

import express from 'express';
const app = express();

app.use(express.json());

app.get('/users/:id', async (req, res) => {
  const user = await db.users.findById(req.params.id);
  if (!user) return res.status(404).json({ error: 'Not found' });
  res.json(user);
});

app.post('/users', async (req, res) => {
  const user = await db.users.create(req.body);
  res.status(201).json(user);
});

app.listen(3000);

gRPC (proto + server)

// user.proto
service UserService {
  rpc GetUser(GetUserRequest) returns (User);
  rpc StreamUsers(stream UserFilter) returns (stream User);
}

message GetUserRequest { string id = 1; }
message User { string id = 1; string email = 2; }
import * as grpc from '@grpc/grpc-js';

const server = new grpc.Server();
server.addService(UserService, {
  getUser: async (call, callback) => {
    const user = await db.users.findById(call.request.id);
    callback(null, user);
  },
});
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => server.start());

WebSocket (real-time)

import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
  ws.on('message', (data) => {
    // 매 broadcast
    wss.clients.forEach(c => c.readyState === 1 && c.send(data));
  });
});

Server-Sent Events

app.get('/events', (req, res) => {
  res.set({
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
  });
  
  const interval = setInterval(() => {
    res.write(`data: ${JSON.stringify({ time: Date.now() })}\n\n`);
  }, 1000);
  
  req.on('close', () => clearInterval(interval));
});

Three-tier deployment

# docker-compose.yml
services:
  client:
    image: my-frontend:latest
    ports: ['80:80']
  
  api:
    image: my-api:latest
    environment:
      - DATABASE_URL=postgres://db:5432/app
      - REDIS_URL=redis://cache:6379
    deploy:
      replicas: 3
  
  cache:
    image: redis:7
  
  db:
    image: postgres:16
    volumes: ['./data:/var/lib/postgresql/data']

API Gateway (Kong / Express middleware)

// 매 simple gateway middleware
import rateLimit from 'express-rate-limit';
import jwt from 'jsonwebtoken';

app.use(rateLimit({ windowMs: 60_000, max: 100 }));

app.use((req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).end();
  try {
    req.user = jwt.verify(token, process.env.JWT_SECRET!);
    next();
  } catch {
    res.status(401).end();
  }
});

app.use('/api/users', proxy('http://user-service:3001'));
app.use('/api/orders', proxy('http://order-service:3002'));

BFF (TypeScript)

// 매 mobile-specific endpoint
app.get('/mobile/dashboard', async (req, res) => {
  const [user, recent_orders, notifications] = await Promise.all([
    userService.get(req.user.id),
    orderService.recent(req.user.id, 5),
    notificationService.unread(req.user.id),
  ]);
  
  // 매 mobile-friendly aggregate
  res.json({
    user: { id: user.id, name: user.name },
    recent: recent_orders.map(o => ({ id: o.id, total: o.total })),
    badge_count: notifications.length,
  });
});

Edge Function (Cloudflare Workers)

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    
    // 매 edge cache
    const cache = caches.default;
    const cached = await cache.match(request);
    if (cached) return cached;
    
    // 매 origin fetch
    const response = await fetch(`https://origin.example.com${url.pathname}`);
    
    // 매 cache
    response.headers.set('Cache-Control', 'public, max-age=60');
    await cache.put(request, response.clone());
    return response;
  },
};

Health check + circuit breaker

app.get('/health', (req, res) => {
  const checks = {
    db: db.isConnected(),
    redis: redis.ping(),
    deps: externalApi.healthy(),
  };
  
  if (Object.values(checks).every(v => v)) {
    res.json({ status: 'ok', checks });
  } else {
    res.status(503).json({ status: 'degraded', checks });
  }
});

🤔 결정 기준

상황 Pattern
Web app Three-tier + REST
Internal services gRPC + service mesh
Real-time WebSocket / SSE
IoT MQTT
Mobile REST + BFF
Offline-first CRDT sync + local-first
Cross-region read Edge + CDN
P2P file BitTorrent / IPFS
Heavy media WebRTC

기본값: REST + 3-tier. 매 internal = gRPC. 매 real-time = WebSocket.

🔗 Graph

🤖 LLM 활용

언제: 매 system design. 매 protocol decision. 매 architecture review. 매 onboarding. 언제 X: 매 single-machine app. 매 P2P-only domain.

안티패턴

  • Single-point-of-failure 무시: 매 multi-AZ 의 X.
  • Chatty client (N+1): 매 BFF 의 lieu.
  • Synchronous chain (5+ hop): 매 cascading failure.
  • No rate limit: 매 abuse vulnerability.
  • REST on real-time: 매 polling overhead.
  • gRPC for browser: 매 매 gateway 필요.
  • No health check: 매 silent degradation.

🧪 검증 / 중복

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — protocol matrix + tier + modern patterns + 매 Express / gRPC / WS / Edge code