소개
현 국내 SI업체 소프트웨어 엔지니어(SA,AA)
다수의 대규모 차세대 프로젝트 개발방법론 및 설계방법 리딩
명지대, 서울과학기술대 클라우드,SW과목 강의
SK C&C,한국정보기술연구원(kitri), LG전자 MSA과정 강의
멀티캠퍼스, 한국표준협회, 한국품질협회 MSA 과정 멘토링,스파로스아카데미 웹개발 과정 멘토링
전문분야 : 개발방법론, 소프트웨어 아키텍처/설계/개발 기법
22년 , 위키북스 "도메인주도로 시작하는 마이크로서비스 개발", 저자
국가평생교육진흥원, K-MOOC "Microservice 설계 및 구현 " 강좌 개발 및 강의
강의
전체3로드맵
전체1수강평
- 좋은 강의 감사합니다.
오명현
2024.10.02
1
게시글
질문&답변
2024.09.18
20분정도에 말씀 하신 내용 질문 있습니다.
움 아키텍처를 설명하기 위해 개념적인 용어들을 사용했지만 이런 기능은 카프카 매커니즘이 이미 제공하고 있습니다. 예를 들어 간단히 구현해 보면 다음과 같습니다. 주문 서비스가 새로운 주문을 생성하면, 이 주문 정보를 Kafka에 이벤트로 보내고, 주문 이력 서비스가 이 이벤트를 읽어 데이터베이스에 주문 이력을 저장한 후, 메시지가 성공적으로 처리되었음을 확인하고 Kafka에서 해당 메시지를 제거하는 방식으로 구현할 수 있습니다. 아래는 이 과정을 간단한 샘플 코드와 함께 설명하겠습니다. 1. Kafka에 주문 이벤트 보내기 (주문 서비스) 주문 서비스가 주문 정보를 Kafka에 보내는 과정입니다. Python의 kafka-python 라이브러리를 사용하여 Kafka에 메시지를 보내는 예제입니다. from kafka import KafkaProducer import json # Kafka 프로듀서 설정 producer = KafkaProducer( bootstrap_servers='localhost:9092', value_serializer=lambda v: json.dumps(v).encode('utf-8') ) # 주문 데이터 order = { 'order_id': '12345', 'customer_id': '67890', 'amount': 100.0 } # Kafka 토픽에 주문 이벤트 전송 producer.send('order-topic', order) producer.flush() 2. 주문 이력 저장 및 Kafka 메시지 삭제 (주문 이력 서비스) 주문 이력 서비스가 Kafka에서 메시지를 읽어 데이터베이스에 저장하고, 저장이 완료되면 Kafka에서 해당 메시지를 제거합니다. Python의 kafka-python 과 mysql-connector-python 을 사용한 예제입니다. from kafka import KafkaConsumer, KafkaProducer import mysql.connector import json # Kafka 컨슈머 설정 consumer = KafkaConsumer( 'order-topic', bootstrap_servers='localhost:9092', auto_offset_reset='earliest', group_id='order-history-group', value_deserializer=lambda x: json.loads(x.decode('utf-8')) ) # Kafka 프로듀서 설정 producer = KafkaProducer( bootstrap_servers='localhost:9092', value_serializer=lambda v: json.dumps(v).encode('utf-8') ) # MySQL 데이터베이스 설정 db_conn = mysql.connector.connect( host='localhost', user='youruser', password='yourpassword', database='yourdatabase' ) cursor = db_conn.cursor() # Kafka 메시지 처리 for message in consumer: order = message.value order_id = order['order_id'] customer_id = order['customer_id'] amount = order['amount'] # 주문 이력을 데이터베이스에 저장 cursor.execute( "INSERT INTO OrderHistory (order_id, customer_id, amount) VALUES (%s, %s, %s)", (order_id, customer_id, amount) ) db_conn.commit() # 메시지 처리가 완료된 후 Kafka에서 메시지 삭제 (offset 커밋) consumer.commit() # 메시지 전송 상태를 확인하고 로그 기록 또는 다른 작업 수행 print(f"Order {order_id} processed and saved to database.") 코드 복사 요약 주문 서비스 : 주문을 Kafka 토픽에 메시지로 전송합니다. 주문 이력 서비스 : Kafka에서 메시지를 읽어 데이터베이스에 주문 이력을 저장합니다. 메시지를 처리한 후 Kafka의 오프셋을 커밋하여 메시지가 더 이상 처리되지 않도록 합니다. 엄밀히 말하면 Kafka에서 오프셋(offset)은 특정 파티션 내에서 메시지의 위치를 나타냅니다. 즉 소비자가 메시지를 처리한 후, Kafka의 컨슈머 그룹은 해당 메시지가 성공적으로 처리되었다는 것을 나타내기 위해 오프셋을 커밋합니다. 오프셋 커밋은 Kafka가 메시지를 어느 지점까지 읽었는지를 기록합니다. 즉, 컨슈머가 다음에 재시작될 때, 마지막으로 커밋된 오프셋부터 메시지를 읽기 시작합니다. 따라서 한번 전달된 메시지가 다시 전달되지 않음을 보장합니다. 그리고 카프카의 메시지는 카프카 로그 보존기간에 따라 자동으로 삭제되게 하면 됩니다.
- 0
- 2
- 32
질문&답변
2024.09.18
CQRS 6분정도 강의 질문드립니다.
안녕하세요. 강의자 입니다. 여기서 이벤트 핸들러는 스프링 이벤트 핸드러 같은 구체적인 기술을 애길한 것은 아니고요. 개념적인 의미로 말씀 드린겁니다. cqrs가 명령( CUD)와 조회( R)를 분리하여 효율성을 높이는 패턴인데요. 예를 들면 주문 서비스가 커맨드 서비스 역할을 수행하고 주문이력 서비스가 조회서비스를 수행한다면, 각기 서비스가 분리되어 있기 때문에 주문이 입력되고, 주문이력이 입력되는 트랜젝션은 분리되기 때문에 분산 트랜젝션이 수행되어 합니다. 이 경우 2개 서비스의 정합성을 맞춰주기 위해 주문 서비스에서 주문 입력 트랜젝션 시 함께 비동기 이벤트를 발생시켜서 주문 이력 서비스에 주문이 들어왔다는 것을 알리는 것이죠. 여기서 주문 이력 서비스의 이벤트 핸들러는 이벤트가 들어왔다는 것을 알아채는 개념적인 기능를 설명하고 있는 겁니다. 여러 가지 기술로 구현 가능할 수 있죠. 주문이력서비스에서는 이벤트 핸들러를 통해 주문이 이벤트를 식별한 뒤 주문 이력 서비스에 주문 이력을 생성하면 주문서비스와 정합성 이 맞게 되는 거죠.
- 0
- 2
- 25
질문&답변
2024.09.09
질문드립니다,
강의자 한정헌입니다. 답변 드리면 다음과 같습니다. 먼저 개념 정의부터 명확히 하면, 노드 및 컨테이너: 노드는 컨테이너가 실행되는 물리적 또는 가상 머신입니다. Kubernetes 클러스터의 각 노드는 여러 컨테이너를 호스팅할 수 있습니다. 따라서 3개의 노드와 8개의 컨테이너가 있는 경우 해당 컨테이너는 Kubernetes 스케줄러의 결정에 따라 3개 노드에 걸쳐 예약됩니다. 스케줄링 : Kubernetes 스케줄러는 노드에 컨테이너(Pod로 패키징됨)를 배치하는 일을 담당합니다. 이는 taints , tolerations, affinity 규칙과 같은 다양한 요소를 기반으로 수행됩니다. 목표는 로드 균형을 맞추고 사용 가능한 리소스를 효율적으로 사용하는 것입니다. 따라서 특정 제약 조건이나 선호도 규칙이 없다고 가정하면 8개의 컨테이너(각 컨테이너가 자체 포드에서 실행된다고 가정)가 3개 노드에 배포됩니다. 그렇지만 분포가 고르지 않을 수도 있습니다. 예를 들어 노드 1에는 포드가 3개 ,노드 2에는 포드가 3개 , 노드 3에는 포드가 2개 있을 수 있습니다. 요 약하면 Kubernetes는 기본적으로 컨테이너를 노드 전체에 균등하게 나누지 않습니다. 대신 리소스 가용성 및 기타 요소를 기반으로 컨테이너를 예약합니다. 배포는 사용자가 설정한 다양한 구성 및 제약 조건의 영향을 받을 수 있습니다. Spring Cloud API Gateway 앞에서 NGINX를 Ingress 컨트롤러로 사용하는 경우 말씀하신 바대로 네트워크 지연 가능성이 있을 수 있으나 매우 경미할 것 같네요. 이를 이중 프록시 레이어로 구성한다고 하는데요. 이런 경우에는 다음과 같이 역할을 줄 수 있겠죠. NGINX 수신 컨트롤러 : Kubernetes 클러스터로 들어오는 외부 트래픽을 처리합니다. SSL 종료, 호스트 이름 또는 경로 기반 라우팅과 같은 작업을 수행하고 로드 밸런싱도 처리할 수 있습니다. Spring Cloud API 게이트웨이 : 클러스터 내에서 작동하며 라우팅, 로드 밸런싱은 물론 인증, 속도 제한 등과 같은 추가 기능을 제공합니다. 이런 경우 각 계층은 추가 처리 및 네트워크 홉으로 인해 약간의 오버헤드 및 잠재적으로 대기 시간이 증가할 수 있습니다. 그렇지만 이런 아키텍처 결정 전에 우선 NGINX와 Spring Cloud API 게이트웨이가 모두 필요한지 고민할 필요가 있을 것 같네요. 또 이런 결정시에는 각 요소의 아래와 같은 장단점을 고려해야 할 것 같네요. NGINX : 클러스터 가장자리에서 트래픽 라우팅 및 로드 밸런싱을 처리하는 데 매우 효과적 Spring Cloud API Gateway : 동적 라우팅, 속도 제한, 서비스 간 통신과 같은 고급 기능을 제공. 네 더 많은 물리적 서버 노드를 추가하여 Kubernetes 클러스터를 확장하는 것은 용량과 복원력을 높이는 강력한 방법이 될 수 있습니다 , 그렇지만 k8s 와 같은 경우 수평형 Pod Autoscaling 를 우선 고려하고 이것이 한계에 도달할 경우 Cluster Autoscaler를 구현하여 단계적으로 Pod 및 노드 수를 동적으로 조정하는 것이 일반적인 방법입니다. 또 Pod Autoscaling 를 고려하여 더 크거나 더 강력한 노드를 추가하는 것이 작은 노드를 많이 추가하는 것보다 더 효과적일 수 있습니다. 당연히 private 망에서도 k8s를 구성할 수 있습니다. 예 로컬에 k8s 구성하는 경우 다음과 같이 구성 가능합니다. 개발/테스트 : 노드 1개(마스터 및 작업자 역할이 모두 포함된 단일 노드 설정) ex) Minikube 기본 프로덕션 : 마스터 노드 1개 + 작업자 노드 1개(고가용성 부족으로 인해 프로덕션에는 적합하지 않음) 권장 프로덕션 : 마스터 노드 3개 + 작업자 노드 2개(고가용성 및 내결함성을 위해)
- 0
- 1
- 32
질문&답변
2024.09.05
레어어드 아케텍처 스타일 질문드립니다.
네 mvc모델에서 j2ee패턴의 dto 나 vo가 모델의 역할을 수행하는 거죠. 즉 레이어드 아키텍처 스타일을 논하면서 mvc모델과 같은 개념으로 이해하는 분들이 많아서 언급한 내용이고요. 굳이 mvc모델을 레이어드 아키텍처와 매핑해보면 프리젠테이션 레이어의 역할과 매핑됩니다. 그리고 두번째 질문에 답변을 드리면, 데이터 엑세스 계층은 제가 레이어드 아키텍처 예를 들며, 4개층 (프리젠테이션,비지니스,퍼시스턴스,데이터베이스) 이렇게 정의했는데 이건 개별 회사 및 시스템 마다 다를 수 있습니다. 용어도 다를 수 있고요. 어떤 프로젝트 에서는 (퍼블리싱,서비스,비지니스로직,데이터엑세스)이런식으로 구분하기도 합니다. 그렇지만 보통 데이터 엑세스 계증은 퍼스시턴스 계층과 같은 용어로 사용됩니다. 감사합니다.
- 0
- 1
- 40
질문&답변
2024.04.27
UserCase가 많은데... 이유?
네 강의자 한정헌입니다. 말씀하신 바대로 헥사고널 아키텍처에서도 예를 들면 CUD단위로 하나의 유스케이스 인터페이스로 묶고 이를 구현하는 입력포트도 하나의 클래스로 작성할 수 있습니다. 처음에 간단했던 cud야 괜찮겠지만 비지니스가 점점 복잡해지면 유지보수가 거듭되면서 이 클래스가 점점 비대해질 가능성이 있습니다. 그래서 저는 기능 단위로 유스케이스와 입력포트를 분리하는 방법을 선호합니다. 유스케이스 단위로 클래스 생성하는 방식에 대해서는 클린코드의 저자 로버트 c 마틴이 ‘ 소리치는 아키텍처(코드의 명칭을 통해 그 의도롤 소리치게 하자.)’라고도 언급하며 강조를 하기도 했습니다. 왜냐면 이렇게 했을 경우 코드명으로 그 의도를 바로 식별할 수 있기 때문이죠. 즉 클래스 명만 보고 어떠한 유스케이스인지 쉽게 인지 가능하기 때문에 테스트 및 유지보수성 높아 질수 있음을 강조했다고 생각합니다. 감사합니다.
- 0
- 1
- 248