TypeScriptκ° μλΉμ€ ν΅μ μ λ°μ κ±Έμ³ νμ μμ μ±μ 보μ₯νμ¬ λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²λ₯Ό μ΄λ»κ² κ°ννλμ§ μμ보μΈμ. λͺ¨λ² μ¬λ‘μ ꡬν μ λ΅μ νμ΅ν©λλ€.
TypeScript λ§μ΄ν¬λ‘μλΉμ€: μλΉμ€ ν΅μ νμ μμ μ± ν보
λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²λ νμ₯μ± μ¦κ°, λ 립μ μΈ λ°°ν¬, κΈ°μ λ€μμ± λ± μλ§μ μ΄μ μ μ 곡ν©λλ€. κ·Έλ¬λ μ¬λ¬ λ 립μ μΈ μλΉμ€λ₯Ό μ‘°μ¨νλ κ²μ λ°μ΄ν° μΌκ΄μ±κ³Ό μμ μ μΈ ν΅μ μ 보μ₯νλ λ° νΉν 볡μ‘μ±μ μΌκΈ°ν©λλ€. κ°λ ₯ν νμ μμ€ν μ κ°μΆ TypeScriptλ μ΄λ¬ν λ¬Έμ λ€μ ν΄κ²°νκ³ λ§μ΄ν¬λ‘μλΉμ€ μνΈμμ©μ κ²¬κ³ ν¨μ ν₯μμν€λ κ°λ ₯ν λꡬλ₯Ό μ 곡ν©λλ€.
λ§μ΄ν¬λ‘μλΉμ€μμ νμ μμ μ±μ μ€μμ±
λͺ¨λ리μ μ ν리μΌμ΄μ μμ λ°μ΄ν° νμ μ μΌλ°μ μΌλ‘ λ¨μΌ μ½λλ² μ΄μ€ λ΄μμ μ μλκ³ μ μ©λ©λλ€. λ°λ©΄μ λ§μ΄ν¬λ‘μλΉμ€λ μ’ μ’ μλ‘ λ€λ₯Έ ν, κΈ°μ λ° λ°°ν¬ νκ²½μ ν¬ν¨ν©λλ€. μΌκ΄λκ³ μ λ’°ν μ μλ λ°μ΄ν° μ ν¨μ± κ²μ¬ λ©μ»€λμ¦μ΄ μμΌλ©΄ ν΅ν© μ€λ₯ λ° λ°νμ μ€ν¨μ μνμ΄ ν¬κ² μ¦κ°ν©λλ€. νμ μμ μ±μ μ»΄νμΌ μ μ격ν νμ κ²μ¬λ₯Ό μ μ©νμ¬ μ΄λ¬ν μνμ μννκ³ , μλΉμ€ κ°μ κ΅νλλ λ°μ΄ν°κ° μ¬μ μ μλ κ³μ½μ μ€μνλλ‘ λ³΄μ₯ν©λλ€.
νμ μμ μ±μ μ΄μ :
- μ€λ₯ κ°μ: νμ κ²μ¬λ κ°λ° μλͺ μ£ΌκΈ° μ΄κΈ°μ μ μ¬μ μΈ μ€λ₯λ₯Ό μλ³νμ¬ λ°νμ λ¬Έμ λ₯Ό λ°©μ§νκ³ λΉμ©μ΄ λ§μ΄ λλ λλ²κΉ λ Έλ ₯μ μ€μ λλ€.
- μ½λ νμ§ ν₯μ: νμ μ£Όμμ μ½λ κ°λ μ±κ³Ό μ μ§λ³΄μμ±μ ν₯μμμΌ κ°λ°μκ° μλΉμ€ μΈν°νμ΄μ€λ₯Ό λ μ½κ² μ΄ν΄νκ³ μμ ν μ μλλ‘ ν©λλ€.
- νμ κ°ν: λͺ νν νμ μ μλ μλΉμ€ κ°μ κ³μ½ μν μ νμ¬ μ¬λ¬ ν κ°μ μνν νμ μ μ΄μ§ν©λλ€.
- μ λ’°λ μ¦κ°: νμ μμ μ±μ λ§μ΄ν¬λ‘μλΉμ€ μνΈμμ©μ μ νμ±κ³Ό μ λ’°μ±μ λν λ ν° νμ μ μ 곡ν©λλ€.
TypeScriptμμ νμ μμ ν μλΉμ€ ν΅μ μ μν μ λ΅
TypeScript κΈ°λ° λ§μ΄ν¬λ‘μλΉμ€μμ νμ μμ ν μλΉμ€ ν΅μ μ λ¬μ±νκΈ° μν΄ μ¬λ¬ μ κ·Ό λ°©μμ μ¬μ©ν μ μμ΅λλ€. μ΅μ μ μ λ΅μ νΉμ ν΅μ νλ‘ν μ½ λ° μν€ν μ²μ λ°λΌ λ¬λΌμ§λλ€.
1. 곡μ νμ μ μ
ν κ°μ§ κ°λ¨ν μ κ·Ό λ°©μμ μ€μ μ μ₯μ(μ: μ μ© npm ν¨ν€μ§ λλ 곡μ Git μ μ₯μ)μ 곡μ νμ μ μλ₯Ό μ μνκ³ κ° λ§μ΄ν¬λ‘μλΉμ€λ‘ κ°μ Έμ€λ κ²μ λλ€. μ΄λ λͺ¨λ μλΉμ€κ° κ΅νλλ λ°μ΄ν° ꡬ쑰μ λν΄ μΌκ΄λ μ΄ν΄λ₯Ό κ°λλ‘ λ³΄μ₯ν©λλ€.
μμ:
λ κ°μ λ§μ΄ν¬λ‘μλΉμ€λ₯Ό κ³ λ €ν΄ λ΄ μλ€: μ£Όλ¬Έ μλΉμ€(Order Service)μ κ²°μ μλΉμ€(Payment Service). μ΄λ€μ μ£Όλ¬Έ λ° κ²°μ μ λν μ 보λ₯Ό κ΅νν΄μΌ ν©λλ€. 곡μ νμ μ μ ν¨ν€μ§λ λ€μμ ν¬ν¨ν μ μμ΅λλ€:
// shared-types/src/index.ts
export interface Order {
orderId: string;
customerId: string;
items: { productId: string; quantity: number; }[];
totalAmount: number;
status: 'pending' | 'processing' | 'completed' | 'cancelled';
}
export interface Payment {
paymentId: string;
orderId: string;
amount: number;
paymentMethod: 'credit_card' | 'paypal' | 'bank_transfer';
status: 'pending' | 'completed' | 'failed';
}
μ£Όλ¬Έ μλΉμ€μ κ²°μ μλΉμ€λ μ΄λ¬ν μΈν°νμ΄μ€λ₯Ό κ°μ Έμ API κ³μ½μ μ μνλ λ° μ¬μ©ν μ μμ΅λλ€.
// order-service/src/index.ts
import { Order } from 'shared-types';
async function createOrder(orderData: Order): Promise<Order> {
// ...
return orderData;
}
// payment-service/src/index.ts
import { Payment } from 'shared-types';
async function processPayment(paymentData: Payment): Promise<Payment> {
// ...
return paymentData;
}
μ₯μ :
- ꡬννκ³ μ΄ν΄νκΈ° μ½μ΅λλ€.
- μλΉμ€ μ λ°μ κ±Έμ³ μΌκ΄μ±μ 보μ₯ν©λλ€.
λ¨μ :
- μλΉμ€ κ°μ κ°ν κ²°ν© β 곡μ νμ λ³κ²½ μ λͺ¨λ μ’ μ μλΉμ€μ μ¬λ°°ν¬κ° νμν©λλ€.
- μλΉμ€κ° λμμ μ λ°μ΄νΈλμ§ μμΌλ©΄ λ²μ μΆ©λμ΄ λ°μν μ μμ΅λλ€.
2. API μ μ μΈμ΄ (μ: OpenAPI/Swagger)
OpenAPI(μ΄μ Swagger)μ κ°μ API μ μ μΈμ΄λ RESTful APIλ₯Ό μ€λͺ νλ νμ€νλ λ°©λ²μ μ 곡ν©λλ€. TypeScript μ½λλ OpenAPI μ¬μμμ μμ±λ μ μμ΄ νμ μμ μ±μ 보μ₯νκ³ μμ©κ΅¬ μ½λλ₯Ό μ€μ λλ€.
μμ:
μ£Όλ¬Έ μλΉμ€λ₯Ό μν OpenAPI μ¬μμ λ€μκ³Ό κ°μ μ μμ΅λλ€:
openapi: 3.0.0
info:
title: Order Service API
version: 1.0.0
paths:
/orders:
post:
summary: Create a new order
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
responses:
'201':
description: Order created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
components:
schemas:
Order:
type: object
properties:
orderId:
type: string
customerId:
type: string
items:
type: array
items:
type: object
properties:
productId:
type: string
quantity:
type: integer
totalAmount:
type: number
status:
type: string
enum: [pending, processing, completed, cancelled]
openapi-typescriptμ κ°μ λꡬλ₯Ό μ¬μ©νμ¬ μ΄ μ¬μμμ TypeScript νμ
μ μμ±ν μ μμ΅λλ€:
npx openapi-typescript order-service.yaml > order-service.d.ts
μ΄κ²μ order-service.d.ts νμΌμ μμ±νλ©°, μ΄ νμΌμλ Order APIλ₯Ό μν TypeScript νμ
μ΄ ν¬ν¨λμ΄ μμ΄ λ€λ₯Έ μλΉμ€μμ νμ
μμ ν ν΅μ μ 보μ₯νλ λ° μ¬μ©λ μ μμ΅λλ€.
μ₯μ :
- νμ€νλ API λ¬Έμν λ° μ½λ μμ±.
- μλΉμ€ κ²μ κ°λ₯μ± ν₯μ.
- μμ©κ΅¬ μ½λ κ°μ.
λ¨μ :
- OpenAPI μ¬μμ νμ΅νκ³ μ μ§λ³΄μν΄μΌ ν©λλ€.
- λ¨μν 곡μ νμ μ μλ³΄λ€ λ³΅μ‘ν μ μμ΅λλ€.
3. gRPCμ νλ‘ν μ½ λ²νΌ
gRPCλ Protocol Buffersλ₯Ό μΈν°νμ΄μ€ μ μ μΈμ΄λ‘ μ¬μ©νλ κ³ μ±λ₯ μ€ν μμ€ RPC νλ μμν¬μ
λλ€. Protocol Buffersλ₯Ό μ¬μ©νλ©΄ νλ«νΌ μ€λ¦½μ μΈ λ°©μμΌλ‘ λ°μ΄ν° ꡬ쑰 λ° μλΉμ€ μΈν°νμ΄μ€λ₯Ό μ μν μ μμ΅λλ€. ts-proto λλ @protobuf-ts/pluginκ³Ό κ°μ λꡬλ₯Ό μ¬μ©νμ¬ Protocol Buffer μ μμμ TypeScript μ½λλ₯Ό μμ±ν μ μμ΄ νμ
μμ μ±κ³Ό ν¨μ¨μ μΈ ν΅μ μ 보μ₯ν©λλ€.
μμ:
μ£Όλ¬Έ μλΉμ€λ₯Ό μν Protocol Buffer μ μλ λ€μκ³Ό κ°μ μ μμ΅λλ€:
// order.proto
syntax = "proto3";
package order;
message Order {
string order_id = 1;
string customer_id = 2;
repeated OrderItem items = 3;
double total_amount = 4;
OrderStatus status = 5;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
}
enum OrderStatus {
PENDING = 0;
PROCESSING = 1;
COMPLETED = 2;
CANCELLED = 3;
}
service OrderService {
rpc CreateOrder (CreateOrderRequest) returns (Order) {}
}
message CreateOrderRequest {
Order order = 1;
}
ts-proto λꡬλ₯Ό μ¬μ©νμ¬ μ΄ μ μμμ TypeScript μ½λλ₯Ό μμ±ν μ μμ΅λλ€:
tsx ts-proto --filename=order.proto --output=src/order.ts
μ΄κ²μ src/order.ts νμΌμ μμ±νλ©°, μ΄ νμΌμλ Order APIλ₯Ό μν TypeScript νμ
κ³Ό μλΉμ€ μ€ν
μ΄ ν¬ν¨λμ΄ μμ΄ λ€λ₯Έ μλΉμ€μμ νμ
μμ νκ³ ν¨μ¨μ μΈ gRPC ν΅μ μ 보μ₯νλ λ° μ¬μ©λ μ μμ΅λλ€.
μ₯μ :
- κ³ μ±λ₯ λ° ν¨μ¨μ μΈ ν΅μ .
- Protocol Buffersλ₯Ό ν΅ν κ°λ ₯ν νμ μμ μ±.
- μΈμ΄ λ 립μ β μ¬λ¬ μΈμ΄λ₯Ό μ§μν©λλ€.
λ¨μ :
- Protocol Buffers λ° gRPC κ°λ νμ΅μ΄ νμν©λλ€.
- RESTful APIλ³΄λ€ μ€μ μ΄ λ³΅μ‘ν μ μμ΅λλ€.
4. λ©μμ§ ν λ° νμ μ μλ₯Ό μ¬μ©ν μ΄λ²€νΈ μ€μ¬ μν€ν μ²
μ΄λ²€νΈ μ€μ¬ μν€ν
μ²μμ λ§μ΄ν¬λ‘μλΉμ€λ λ©μμ§ ν(μ: RabbitMQ, Kafka)λ₯Ό ν΅ν΄ λΉλκΈ°μ μΌλ‘ ν΅μ ν©λλ€. νμ
μμ μ±μ 보μ₯νλ €λ©΄ κ΅νλλ λ©μμ§μ λν TypeScript μΈν°νμ΄μ€λ₯Ό μ μνκ³ , μ€ν€λ§ μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬(μ: joi λλ ajv)λ₯Ό μ¬μ©νμ¬ λ°νμμ λ©μμ§λ₯Ό μ ν¨μ± κ²μ¬ν©λλ€.
μμ:
μ νμ μ¬κ³ μμ€μ΄ λ³κ²½λ λ μ΄λ²€νΈλ₯Ό κ²μνλ μ¬κ³ μλΉμ€(Inventory Service)λ₯Ό κ³ λ €ν΄ λ΄ μλ€. μ΄λ²€νΈ λ©μμ§λ λ€μκ³Ό κ°μ΄ μ μλ μ μμ΅λλ€:
// inventory-event.ts
export interface InventoryEvent {
productId: string;
newStockLevel: number;
timestamp: Date;
}
export const inventoryEventSchema = Joi.object({
productId: Joi.string().required(),
newStockLevel: Joi.number().integer().required(),
timestamp: Joi.date().required(),
});
μ¬κ³ μλΉμ€λ μ΄ μΈν°νμ΄μ€λ₯Ό μ€μνλ λ©μμ§λ₯Ό κ²μνκ³ , λ€λ₯Έ μλΉμ€(μ: μλ¦Ό μλΉμ€(Notification Service))λ μ΄λ¬ν μ΄λ²€νΈλ₯Ό ꡬλ νκ³ νμ μμ ν λ°©μμΌλ‘ μ²λ¦¬ν μ μμ΅λλ€.
// notification-service.ts
import { InventoryEvent, inventoryEventSchema } from './inventory-event';
import Joi from 'joi';
async function handleInventoryEvent(message: any) {
const { value, error } = inventoryEventSchema.validate(message);
if (error) {
console.error('Invalid inventory event:', error);
return;
}
const event: InventoryEvent = value;
// Process the event...
console.log(`Product ${event.productId} stock level changed to ${event.newStockLevel}`);
}
μ₯μ :
- λμ¨νκ² κ²°ν©λ μλΉμ€ λ° ν₯μλ νμ₯μ±.
- λΉλκΈ° ν΅μ .
- μ€ν€λ§ μ ν¨μ± κ²μ¬λ₯Ό ν΅ν νμ μμ μ±.
λ¨μ :
- λκΈ° ν΅μ μ λΉν΄ 볡μ‘μ± μ¦κ°.
- λ©μμ§ ν λ° μ΄λ²€νΈ μ€ν€λ§μ μ μ€ν κ΄λ¦¬κ° νμν©λλ€.
νμ μμ μ± μ μ§λ₯Ό μν λͺ¨λ² μ¬λ‘
λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²μμ νμ μμ μ±μ μ μ§νλ €λ©΄ κ·μ¨κ³Ό λͺ¨λ² μ¬λ‘ μ€μκ° νμν©λλ€:
- μ€μ μ§μ€μ νμ μ μ: 곡μ νμ μ μλ₯Ό λͺ¨λ μλΉμ€κ° μ κ·Όν μ μλ μ€μ μ μ₯μμ μ μ₯ν©λλ€.
- λ²μ κ΄λ¦¬: 곡μ νμ μ μμ μλ―Έλ‘ μ λ²μ κ΄λ¦¬(semantic versioning)λ₯Ό μ¬μ©νμ¬ λ³κ²½ μ¬ν λ° μμ‘΄μ±μ κ΄λ¦¬ν©λλ€.
- μ½λ μμ±: μ½λ μμ± λꡬλ₯Ό νμ©νμ¬ API μ μ λλ Protocol Buffersμμ TypeScript νμ μ μλμΌλ‘ μμ±ν©λλ€.
- μ€ν€λ§ μ ν¨μ± κ²μ¬: νΉν μ΄λ²€νΈ μ€μ¬ μν€ν μ²μμ λ°μ΄ν° 무결μ±μ 보μ₯νκΈ° μν΄ λ°νμ μ€ν€λ§ μ ν¨μ± κ²μ¬λ₯Ό ꡬνν©λλ€.
- μ§μμ ν΅ν©: CI/CD νμ΄νλΌμΈμ νμ κ²μ¬ λ° λ¦°ν μ ν΅ν©νμ¬ μ€λ₯λ₯Ό μ‘°κΈ°μ κ°μ§ν©λλ€.
- λ¬Έμν: API κ³μ½ λ° λ°μ΄ν° ꡬ쑰λ₯Ό λͺ ννκ² λ¬Έμνν©λλ€.
- λͺ¨λν°λ§ λ° κ²½κ³ : νμ μ€λ₯ λ° λΆμΌμΉμ λν΄ μλΉμ€ ν΅μ μ λͺ¨λν°λ§ν©λλ€.
κ³ λ €ν κ³ κΈ μ¬ν
API κ²μ΄νΈμ¨μ΄: API κ²μ΄νΈμ¨μ΄λ νμ κ³μ½μ μννκ³ λ°±μλ μλΉμ€μ λλ¬νκΈ° μ μ μμ²μ μ ν¨μ± κ²μ¬νλ λ° μ€μν μν μ ν μ μμ΅λλ€. λν λ€λ₯Έ νμ κ°μ λ°μ΄ν°λ₯Ό λ³ννλ λ° μ¬μ©λ μ μμ΅λλ€.
GraphQL: GraphQLμ μ¬λ¬ λ§μ΄ν¬λ‘μλΉμ€μμ λ°μ΄ν°λ₯Ό 쿼리νλ μ μ°νκ³ ν¨μ¨μ μΈ λ°©λ²μ μ 곡ν©λλ€. GraphQL μ€ν€λ§λ TypeScriptλ‘ μ μλ μ μμ΄ νμ μμ μ±μ 보μ₯νκ³ κ°λ ₯ν λꡬλ₯Ό μ¬μ©ν μ μκ² ν©λλ€.
κ³μ½ ν μ€νΈ: κ³μ½ ν μ€νΈλ μλΉμ€κ° μλΉμμκ² μ μλ κ³μ½μ μ€μνλμ§ νμΈνλ λ° μ€μ μ λ‘λλ€. μ΄λ νΈνμ±μ΄ κΉ¨μ§λ λ³κ²½μ λ°©μ§νκ³ μλΉμ€ κ°μ νΈνμ±μ 보μ₯νλ λ° λμμ΄ λ©λλ€.
λ€μ€ μΈμ΄ μν€ν μ²: μ¬λ¬ μΈμ΄λ₯Ό νΌν©νμ¬ μ¬μ©ν λ κ³μ½ λ° λ°μ΄ν° μ€ν€λ§λ₯Ό μ μνλ κ²μ΄ ν¨μ¬ λ μ€μν΄μ§λλ€. JSON Schema λλ Protocol Buffersμ κ°μ νμ€ νμμ μλ‘ λ€λ₯Έ κΈ°μ κ°μ 격차λ₯Ό ν΄μνλ λ° λμμ΄ λ μ μμ΅λλ€.
κ²°λ‘
νμ μμ μ±μ κ²¬κ³ νκ³ μ λ’°ν μ μλ λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²λ₯Ό ꡬμΆνλ λ° νμμ μ λλ€. TypeScriptλ νμ κ²μ¬λ₯Ό μ μ©νκ³ μλΉμ€ κ²½κ³ μ λ°μ κ±Έμ³ λ°μ΄ν° μΌκ΄μ±μ 보μ₯νλ κ°λ ₯ν λꡬμ κΈ°μ μ μ 곡ν©λλ€. μ΄ λ¬Έμμ μ€λͺ λ μ λ΅κ³Ό λͺ¨λ² μ¬λ‘λ₯Ό μ±νν¨μΌλ‘μ¨ ν΅ν© μ€λ₯λ₯Ό ν¬κ² μ€μ΄κ³ μ½λ νμ§μ ν₯μμν€λ©° λ§μ΄ν¬λ‘μλΉμ€ μνκ³μ μ λ°μ μΈ λ³΅μλ ₯μ λμΌ μ μμ΅λλ€.
곡μ νμ μ μ, API μ μ μΈμ΄, Protocol Buffersλ₯Ό μ¬μ©ν gRPC λλ μ€ν€λ§ μ ν¨μ± κ²μ¬λ₯Ό μ¬μ©ν λ©μμ§ ν μ€ μ΄λ€ κ²μ μ ννλ , μ μ μλκ³ κ°μ λ νμ μμ€ν μ΄ μ±κ³΅μ μΈ λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²μ μ΄μμ΄λΌλ μ μ κΈ°μ΅νμμμ€. νμ μμ μ±μ μμ©νλ©΄ λ§μ΄ν¬λ‘μλΉμ€κ° κ³ λ§μν κ²μ λλ€.
μ΄ λ¬Έμλ TypeScript λ§μ΄ν¬λ‘μλΉμ€μμ νμ μμ μ±μ λν ν¬κ΄μ μΈ κ°μλ₯Ό μ 곡ν©λλ€. μννΈμ¨μ΄ μν€ν νΈ, κ°λ°μ λ° κ²¬κ³ νκ³ νμ₯ κ°λ₯ν λΆμ° μμ€ν ꡬμΆμ κ΄μ¬ μλ λͺ¨λ μ¬λμ λμμΌλ‘ ν©λλ€.