8.3 KiB
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 |
|
none | A | 0.95 | applied |
|
2026-05-10 | pending |
|
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
- 부모: Architecture-Styles · Distributed-Systems · Network
- 변형: REST · gRPC · GraphQL · WebSocket · MQTT · WebRTC
- 응용: BFF · API-Gateway · Service-Mesh · Edge-Computing
- 대안: P2P · Local-First · Serverless · CRDT
- Adjacent: CAP-Theorem · Availability-and-Persistence · Microservices
🤖 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.
🧪 검증 / 중복
- Verified (Roy Fielding REST thesis, gRPC docs, BFF pattern Sam Newman).
- 신뢰도 A.
- Related: Architecture-Styles · Microservices · CAP-Theorem · Bounded-Contexts · Availability-and-Persistence.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — protocol matrix + tier + modern patterns + 매 Express / gRPC / WS / Edge code |