모놀리식
Monolithic
모놀리식 아키텍처는 모든 기능이 하나의 코드베이스와 배포 단위로 통합된 전통적인 소프트웨어 구조입니다. 개발 초기에 단순하고 빠르지만, 규모가 커지면 유지보수와 확장에 어려움이 발생합니다.
Monolithic
모놀리식 아키텍처는 모든 기능이 하나의 코드베이스와 배포 단위로 통합된 전통적인 소프트웨어 구조입니다. 개발 초기에 단순하고 빠르지만, 규모가 커지면 유지보수와 확장에 어려움이 발생합니다.
모놀리식(Monolithic) 아키텍처는 애플리케이션의 모든 기능(UI, 비즈니스 로직, 데이터 접근)이 하나의 코드베이스에 통합되어 단일 단위로 빌드되고 배포되는 전통적인 소프트웨어 구조입니다.
myapp/
├── src/
│ ├── controllers/ # 모든 HTTP 컨트롤러
│ │ ├── UserController.ts
│ │ ├── OrderController.ts
│ │ └── ProductController.ts
│ ├── services/ # 비즈니스 로직 (모두 같은 폴더)
│ │ ├── UserService.ts
│ │ ├── OrderService.ts
│ │ └── ProductService.ts
│ ├── models/ # 데이터베이스 모델 (공유)
│ │ ├── User.ts
│ │ ├── Order.ts
│ │ └── Product.ts
│ └── app.ts # 단일 진입점
├── package.json
└── Dockerfile # 하나의 이미지
// services/OrderService.ts
import { UserService } from './UserService';
import { ProductService } from './ProductService';
import { Order } from '../models/Order';
export class OrderService {
constructor(
private userService: UserService, // 직접 의존
private productService: ProductService // 직접 의존
) {}
async createOrder(userId: string, productIds: string[]) {
// 함수 호출로 바로 접근 (네트워크 비용 없음)
const user = await this.userService.findById(userId);
const products = await this.productService.findByIds(productIds);
// 같은 DB 트랜잭션 가능
const order = new Order({ user, products });
await order.save();
return order;
}
}
// 안티패턴: 순환 의존, 명확하지 않은 경계
import { OrderService } from './OrderService';
import { UserService } from './UserService';
import { NotificationService } from './NotificationService';
export class ProductService {
// 모든 서비스가 서로를 알고 있음
constructor(
private orderService: OrderService,
private userService: UserService,
private notificationService: NotificationService
) {}
async updatePrice(productId: string, newPrice: number) {
// 도처에서 다른 서비스 호출
await this.product.updatePrice(newPrice);
// 연관된 주문 가격도 업데이트 (경계 침범)
await this.orderService.recalculateOrdersWithProduct(productId);
// 관심 있는 사용자에게 알림 (더 복잡해짐)
const users = await this.userService.findWatchingProduct(productId);
await this.notificationService.notifyPriceChange(users, productId);
}
}
"배포하는데 30분이나 걸리고, 한 줄 고쳤는데 전체 테스트를 다시 돌려야 해요."
"모놀리식의 한계가 왔네요. 모듈 경계를 먼저 정리해서 Modular Monolith로 전환하고, 트래픽이 많은 부분부터 점진적으로 마이크로서비스로 분리하는 전략을 추천해요."
"마이크로서비스가 트렌드라고 하던데, 처음부터 마이크로서비스로 시작하면 안 되나요?"
"Monolith First 원칙이 있어요. 도메인을 충분히 이해하기 전에 마이크로서비스로 분리하면 경계를 잘못 나눠서 나중에 더 고생해요. 모놀리식으로 시작해서 도메인이 명확해지면 그때 분리하는 게 낫습니다."
Big Ball of Mud: 모놀리식이라도 내부 구조가 없으면 "진흙 덩어리"가 됩니다. 레이어드 아키텍처나 모듈 구조를 유지하세요.
분산 모놀리스: 마이크로서비스처럼 분리했지만 강하게 결합된 상태. 모놀리식의 단점 + 분산 시스템의 복잡성을 모두 가집니다.
팁: 모놀리식은 나쁜 게 아닙니다. Shopify, Stack Overflow 등 대형 서비스도 모놀리식을 잘 운영하고 있어요. 중요한 건 코드 품질과 모듈화입니다.