피드백
팀 프로젝트 결과
어제 프로젝트에서 부족했던 점을 작성한 회고를 기반으로 진행 과정과 결과를 지켜보신 튜터님과 매니저님께 빠트린 부분이나 노하우에 관해 조언을 부탁드렸다.
튜터님
- 배려로 인한 단호함 부재
17조의 가장 큰 단점은 단호한 리더나 팀원이 없었다는 점이다. 배려심이 너무 많아서, 이를 실행으로 옮길 시간적 여유가 사라졌다. 의견 충돌 시 단호하게 결정하고 방향성을 제시하는 사람이 필요했다. - 모호한 요구사항에 대한 대처
현업에서도 모호한 요구사항은 자주 발생하며, 기획자보다 개발자가 정책을 더 잘 이해하는 경우가 있다. 의견 충돌이 발생하거나 결정이 어려운 경우 매니저나 튜터와 빠르게 논의하여 해결해야 한다. 토론도 물론 중요하지만, 빠른 의사결정과 의견 정리가 필요하다. - 부족한 시간에서 우선순위 관리
프로젝트 진행 중 우선순위를 정하는 것이 쉬운 것은 아니다. 팀의 의견을 대략적으로 정한후, 이를 튜터와 논의하여 기간을 설정하는 것도 좋겠다. 필수 기능을 우선적으로 개발하는게 너무 중요하고, 코드 프리징 이후에는 버그 수정과 고도화 작업에 집중해야 한다. - 일정체계와 추가 의견사항
프로젝트 초기부터 일정 관리 체계를 확실히 잡고 관리하는 것이 중요하다. 일정 및 기술 결정 시 팀원 간 명확한 합의가 필요하며, 이후에는 모두가 합의한 방향으로 밀어붙일 수 있어야 한다. - 문제 상황에 대한 사전 공유
스크럼 회의 때 에러나 문제 상황을 사전에 공유하여 팀 차원에서 해결책을 모색해야 한다. 최소한의 통합 테스트를 진행하거나, MSA 환경에서는 모킹 API라도 제공하여 테스트가 가능하도록 해야 한다. - 개발 우선순위
“내 작업 먼저 처리하고, 다른 사람 작업 도와주기” 방식으로 팀의 진행도에 관여하는 것은 좋은 방법이다. 기술적인 조언이 아니더라도 다른 팀원을 도와주는 제스처만으로도 전체 속도와 팀 효율을 높이는 데 큰 도움을 주는 것이다. - 공유 작업과 컨벤션 도입
팀이 귀찮아하거나 번거로워하는 일은 혼자 시도해보고, 완성된후 다른 팀원들에게 제시하여 진행을 하는 방법도 좋을 것 같다.
총괄 매니저님
- 프로젝트 매니징을 꽉 잡고 진행 해줄 수 있는 사람이 없었던게 아쉽다.
- 팀 기간동안 스크럼같은 부분에서 컨벤션을 정해 진행 과정과 문제 상황에 대한 공유가 확실히 가져갔으면 더 좋았을 것 같다.
- 모든 개발자나 실무자가 마감기한에 대해 모르겠어요 라는 답을 하면 안된다. 하지만 그런 경우가 발생한 경우 차질 없이 일정을 공유해야 협업을 진행할 수 있다는 필요성을 강조해보는 시도를 할 수 있을 것 같다. 스크럼 과정에서도 이 부분을 컨벤션으로 강조해놓으면 넛지한 방법이 될 수 있을 것 같다.
비싼 요청
개인 과제에서 존재하는 상품인지 검증하는 API를 반복문을 통한 다량 전송됐던 부분을 비싼 연산 이라고 표현을 해주셔서, 배열을 통해 한번에 검증을 처리하는 방법을 생각해볼 수 있었습니다. 공부하다보니 비싼요청에 대한 고민이 추가적으로 생겼습니다.
답변
- 로깅을 비롯한 서비스 관리 목적의 요청도 가능한 한 줄여야할까요? 아니면 예외적으로 보되, 캐싱을 활용하거나 배치를 통해 주기적으로 DB에 반영하는 접근이 일반적일까요?
보통 로깅같은 경우 에어플로우 설정을 통해 로그를 따로 수집하는 곳에 설정을 하기 때문에 명시적으로 API 호출하듯이 보내진 않아도 될 것 같다. 운영적으로 필요해서 비즈니스 로직 이후에 후처리되는 부분이 있을 수 있는데, 예를 들어 상품에 대한 정산 기능이 필요한 경우 바로바로 처리하지 않아도 비동기로 뺄 것 같다.
- 서비스 로직의 설계까지는 관여하지 않는 범위에서 로직 자체로서 줄일 수 있는 부분만 고려하면 될까요?
처음부터 캐치할 수 있으면 캐치하는 것이 좋다. 분산환경의 경우 어떤 데이터가 어떤 주기를 갖게 되는지 고민이 중요하다. 비동기, 동기, 배치 등 어떻게 처리할지 같이 해결될 수 있다. 모니터링을 했을때 병목현상 발생되는 것을 확인한 이후에 발견된 부분을 리팩토링하는 것도 일반적이다.
- 다음 프로젝트 관련 조언
모니터링 툴을 붙이고 초반에 개발 했을 때와 후반에 개발 했을 때의 성능차이를 보여주는 것도 좋을 것 같다. 비효율적이게 최소 작동범위인 MVP로 개발을 하고 이후에 동시성 이슈나 API가 밀리는 문제와 같이 발견되는 문제들을 어떻게 개선할 수 있을지 고민하여 캐시, 대기열, 분산락 등 해결을 한 후에 전후의 성능차이를 비교하면 좋을 것 같다. 오히려 비효율적이라고 생각했지만 생각보다 괜찮게 작동하는 부분을 발견하게 되는 경우도 있다.
RabbitMQ
데이터(메시지)를 송신자(프로듀서)로부터 수신자(컨슈머)에게 전달하는 중간 매개체 역할인 메시지 브로커이다. 메시지를 큐에 저장하고, 필요할때 적절한 수신자에게 전달한다. 비동기 처리, 부하 분산, 내결함성이 특징이다.
장점
- 메시지를 디스크에 저장하여 시스템 장애시에도 메시지가 손실되지 않도록한다.
- 메시지가 성공자에게 소비자에게 전달되었는지 확인하는 ACK매커니즘을 지원한다.
- 다양한 메시지 전달 패턴과 프로토콜을 지원한다.
- 클러스터링을 통해 여러 노드에서 구성된 환경에서 높은 가용성과 부하 분산을 제공한다.
- 적절히 구성된 RabbitMQ는 높은 메시지 처리량을 제공하여 대규모 애플리케이션에서도 효과적이다.
Exchange
Direct Exchange
라우팅 키와 바인딩 키가 정확히 일치하는 큐로 메시지를 전달한다. 대부분의 현업에서 이 방법을 사용한다.
Topic Exchange
라우팅 키의 패턴을 사용하여 메시지를 라우팅한다. 패턴에는 와일드카드 *
(단어 하나)와 #
(0개 이상의 단어, **
과 유사한 것 같다.)가 사용된다.
Fanout Exchange
라우팅 키를 무시하고 바인딩된 모든 큐로 메시지를 브로드캐스트한다.
Headers Exchange
라우팅 키 대신 메시지의 헤더를 기반으로 메시지를 라우팅한다.
Kafka
실시간 데이터 피드의 빅 데이터 처리를 목적으로 사용한다. 메시지 큐와 유사하지만, 대용량 데이터 스트림을 저장하고 실시간으로 분석하거나 처리하는데 중점을 둔다.
장점
- 데이터를 여러 브로커에 복제하여 저장하므로, 단일 브로커 장애 시에도 데이터 손실을 방지한다.
- 데이터가 소비자에게 성공적으로 전달되었는지 확인하는 기능을 지원하고, 여러 소비자가 동시에 데이터를 구독할 수 있다.
- Kafka의 프로토콜을 사용하지만 다양한 클라이언트를 통해 다른 언어에서도 사용할 수 있다.
- 클러스터링을 통한 분산처리를 지원하고, 쉽게 확장할 수 있다.
- 데이터 전송의 지연을 최소화하여 실시간으로 빠르게 처리할 수 있다.
- 다양한 관리도구로 모니터링할 수 있고 플러그인으로 확장할 수 있다.
RabbitMQ와 Kafka 비교
공통 단점
- 초기 설정이 굉장히 복잡하고 설정 값이 많으며 운영 관리에 추가적인 노력이 필요하다.
- 트래픽이 높은 상황에서는 브로커의 오버헤드가 발생할 수 있다. 그래서 적절한 클러스터링과 최적화가 필요하다.
흐름 비교
RabbitMQ
- 메시지 생성 → 익스체인지로 전송 (프로듀서 → 익스체인지)
- 익스체인지에서 라우팅 → 큐에 메시지 저장
- 바인딩 키와 라우팅 키의 일치여부로 큐가 결정한다.
- 컨슈머가 큐에서 메시지 소비
- 메시지 처리 완료 → ACK 응답 → 큐에서 메시지 제거
Kafka
- 메시지 생성 → 토픽에 저장 (프로듀서 → 토픽)
- 토픽 내에서 메시지가 파티션으로 분배
- 키(Key)로 특정 파티션 지정 가능하다.
- 키가 없으면 Kafka가 파티션을 자동 분배한다.
- 컨슈머 그룹이 토픽을 구독하여 파티션을 나누어 처리
- 메시지 처리 완료 → 오프셋 커밋 → 이후 처리 상태 기록
구성 요소
구성 요소 | RabbitMQ | Kafka |
---|---|---|
메시지 | 데이터 단위로 큐(queue)에 저장 후 소비자에게 전달. | 데이터 단위로 토픽(topic)에 저장되며, 파티션(partition)을 통해 관리. |
프로듀서 | 메시지를 생성하고 익스체인지(exchange)로 전송. | 메시지를 생성하고 토픽(topic)으로 전송. |
라우팅 | 익스체인지(exchange)를 통해 메시지를 큐(queue)로 전달. | 키(key)를 기반으로 메시지를 특정 파티션(partition)으로 라우팅. |
저장소 | 큐(queue): 메시지를 저장하며 컨슈머가 가져갈 때까지 대기. | 파티션(partition): 토픽의 물리적 분할 단위로 메시지를 순차적으로 저장. |
컨슈머 | 큐(queue)에서 메시지를 가져와 처리. 라운드 로빈 방식으로 큐를 컨슈머 간에 분배. | 토픽(topic)을 구독하여 메시지를 가져와 처리. 컨슈머 그룹을 통해 파티션을 병렬로 처리. |
라우팅 기준 | 바인딩 키(binding key)와 라우팅 키의 일치 여부에 따라 큐로 메시지 전달. | 키(key)를 기반으로 특정 파티션에 메시지를 저장. 키가 없으면 라운드 로빈 방식으로 분배. |
순서 보장 | 같은 큐(queue) 내 메시지 순서가 보장됨. | 같은 파티션(partition) 내 메시지 순서가 보장됨. |
브로커 | 중앙 브로커가 큐와 컨슈머 간의 메시지 라우팅 및 저장을 관리. | 분산된 브로커가 토픽과 파티션을 관리하며, 여러 브로커가 클러스터를 형성. |
메타데이터 관리 | 없음. | 주키퍼(Zookeeper) 또는 Kafka 자체 메타데이터로 클러스터 관리. |