시스템 아키텍트시스템 architect

마이크로서비스 간의 상호작용을 올바르게 구성하여 결합도를 최소화하고 확장성을 극대화하는 방법은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

마이크로서비스 간의 결합도 최소화는 현대 아키텍처의 주요 원칙 중 하나입니다. 이는 비동기 상호작용(메시지 큐 또는 이벤트 버스를 통해), 필요하지 않은 직접 동기 HTTP 호출의 회피, 명확한 API 계약의 설정을 통해 이루어집니다.

인기 있는 방법은 메시지 브로커(RabbitMQ, Kafka, NATS)를 사용하는 것으로, 여기서 마이크로서비스는 자신의 상태에 대한 이벤트를 게시하고, 구독자는 이에 반응합니다.

예를 들어, Node.js에서 Kafka의 이벤트를 게시하고 처리하는 방법은 다음과 같습니다:

// producer.js const { Kafka } = require('kafkajs') const kafka = new Kafka({ clientId: 'order-service', brokers: ['kafka01:9092'] }) const producer = kafka.producer() await producer.connect() await producer.send({ topic: 'orders', messages: [ { value: JSON.stringify({orderId: 123}) } ] }) await producer.disconnect() // consumer.js const consumer = kafka.consumer({ groupId: 'payment-group' }) await consumer.connect() await consumer.subscribe({ topic: 'orders', fromBeginning: true }) await consumer.run({ eachMessage: async ({ topic, partition, message }) => { const order = JSON.parse(message.value.toString()) // 주문 처리 }})

주요 특징:

  • 마이크로서비스는 형식화된 API 또는 중개자를 통해 상호작용합니다(큐, 버스)
  • 각 서비스는 데이터베이스를 별도로 가져야 하며(Database per Service), 이를 통해 잠금 및 경쟁을 피합니다.
  • 기존 시스템을 변경하지 않고 새로운 서비스가 즉시 추가될 수 있습니다.

함정 질문.

질문: 하나의 큰 프로젝트라면 여러 마이크로서비스가 공통 데이터베이스를 사용하는 것이 가능한가요?

아니오, 이는 독립성 원칙을 위반하며, tight coupling을 초래하고 확장성과 유지보수성을 악화시킵니다. 개별 데이터베이스 또는 스키마를 사용해야 합니다.

질문: 시스템 확장 시 서비스 간의 동기 HTTP 상호작용이 허용되는 관행인가요?

동기 HTTP 요청은 확장성이 떨어지고 병목 현상이 발생할 수 있습니다. 비동기 메커니즘을 적용하는 것이 권장되며, 절대적인 필요가 있을 경우에만 동기 호출을 사용해야 합니다.

질문: 시스템 아키텍처를 변경하지 않고 마이크로서비스를 인스턴스 수에 따라만 확장할 수 있나요?

아니오, 단순히 인스턴스 수를 늘리는 것으로는 결합도 문제나 아키텍처에서의 병목 현상을 해결할 수 없습니다. 병목 현상 분석, 큐 도입, 캐싱 및 서비스 책임 분리가 필요합니다.