2/28/2025

DB 설계: 축약어 vs 풀네임, 어떤 것을 선택할까?


프로젝트 진행을 준비중인데., 함께 일하는 동료가 질문을 했다.

“레거시 시스템들은 모두 축약어로 되어 있던데., 새로 생성하는 디비 설계 시 축약어를 써야 할까요?”


“그 축약어가 사람이 인지하기 쉽던가요? 어렵던가요?”


“어렵죠. ERD 논리모델로 봐야 이해가 되는데., 이게 현행화가 안되어 있는 경우가 많아요.”


이런 대화를 나누다가 문득 궁금해졌다. Gen AI가 활발하게 사용되고 있는 2025년 왜 우리는 이런 이야기를 해야 하는가? 그래서 찾아본 내용을 글로 정리한다.


데이터베이스(DB) 설계는 모든 프로덕트의 뼈대다. 그러나 테이블명과 컬럼명을 정할 때, 축약어를 사용할지 풀네임을 사용할지 의견이 갈린다. 현재 트렌드는 무엇이고, 왜 이런 논쟁이 생겼는지 살펴보자.


축약어의 기원과 이유

과거에는 시스템 자원의 한계와 데이터베이스 성능 최적화가 중요한 이슈였던 시절이 있었다. 특히 초기 컴퓨터 환경에서는 저장 공간이 부족했고, 네트워크 속도나 처리 능력이 제한적이었기 때문에, 테이블이나 컬럼 이름을 짧게 줄여서 사용하는 것을 선호했다.


예를 들어, cust(customer), addr(address), emp(employee)와 같은 축약어가 널리 사용되었다. 이렇게 축약어를 사용함으로써 데이터베이스의 공간을 절약하고 코드의 길이를 줄일 수 있었던 것이다.


하지만 이 방식에는 문제가 있었다. 축약어가 지나치게 많거나 모호하게 사용되면, 새로 투입되는 사람은 이를 이해하기 어려워지는 문제가 있다. 또한, 데이터베이스의 구조가 점점 복잡해지고 많은 데이터가 관리되는 상황에서 직관적인 이름이 더욱 중요한 요소로 떠오르게 되었다.


즉, 축약어는 효율성을 상징했지만, 가독성을 희생시켰다.


현재 트렌드

현재는 데이터베이스 테이블과 컬럼 이름을 지을 때, 명확하고 직관적인 이름이 중요시되고 있다. 이는 소프트웨어 개발의 전반적인 변화와 관련이 있다. 코드가 길어지고 복잡해지는 만큼, 개발자들은 가독성 높은 코드 작성을 추구한다. 데이터베이스 설계도 마찬가지로 직관적인 이름을 통해 사람들이 편의를 고려하는 방향으로 바뀌고 있다.


예를 들어, cust_name, usr_addr 처럼 축약어를 사용하기 보다는, customer_name과 user_address 처럼 풀네임을 사용하는 것이 일반적이다. 이렇게 하면 컬럼이나 테이블을 이해하는데 더 직관적으로 파악할 수 있어 유지보수와 디버깅이 훨씬 수월하다.


이렇게 바뀐 이유는 아래와 같다.


  • 가독성 우선: 현대 개발은 협업과 유지보수가 핵심이라, 사람이 쉽게 이해하는 이름이 선호된다. 더군다나 Gen AI의 시대에서 말이다.

  • 기술 진화: PostgreSQL은 63자, 오라클은 30자까지 식별자를 지원하며, 성능 차이는 미미하다. 축약의 필요성이 줄었다.

  • 문서화 감소: 풀네임은 자체 설명적이기에 별도 명세서 없이도 이해가 가능하다.

  • 클린 코드 철학의 확산: “클린 코드” 철학은 코딩 시 직관적이고 읽기 쉬운 코드를 작성하는데 초점을 맞추고 있다. DB 설계도 예외는 아니다.

  • 협업 및 확장성: 프로덕트가 점점 커짐에 따라 다른 사람이 이해하기 쉬운 이름이 더욱 중요해졌다. 축약어가 많으면 혼란을 초래할 수 있다.


그러나 레거시 시스템이 많은 곳은 아직도 축약어의 잔재가 남아있다. 혹은 도메인별 관습이 강한 경우에도 축약어가 남아 있는 경우가 있다.


결론

데이터베이스 설계에서 이름 짓기는 단순히 개인적인 취향의 문제가 아니다. 시간과 기술의 발전에 따라 더 이상 축약어만을 고집하기보다는 직관적이고 명확한 이름을 사용하는 것이 더욱 중요해졌다.


물론, 간단한 약어는 여전히 유용할 수 있지만, 그 사용은 줄어들고 대신 풀네임을 사용하여 가독성과 유지 보수성을 높이는 것이 꽤 오래전부터 트렌드로 자리잡고 있다.


끝으로,

이 글을 읽는 분들은 https://vertabelo.com/blog/database-naming-convention/ 링크를 참고해서 최악을 피했으면 좋겠다.


2/14/2025

Cursor AI 사용해보고 느낀 점

 


처음에는 Cursor AI IDE를 그저 또 다른 AI 코딩 도구로 간주했었다.

Cursor AI, Windsurf, Cline등 다양한 것을 써보고, 지금 시점에는 관점이 상당히 바뀌었기에 이에 대해 글을 쓰기로 결정 했다.

AI 코딩 도구에 대한 나의 핵심 철학은 방대한 양의 코드를 생성하는 것이 아니다.

대신, 진부하고 지루한 작업을 처리하고, 반복적인 코딩 작업을 가속화하여, 비즈니스 로직, 아키텍처, 문제 해결등에 집중할 수 있게 해주는 비서를 찾는 개념이다.

Cursor AI에 대한 현재까지의 나의 느낌은 빠른 프로토타입 개발에서 빛을 발하고, 반복적인 코딩 블록에 대한 인지 부하를 줄여준다고 생각된다. 같이 사용하고 있는 동료도 나와 같은 생각을 하고 있고, 현재는 리팩토링 관점에서 접근해보고 있다.

기능

Cursor는 AI 기반 IDE 이다.

Cursor AI는 Visual Studio Code의 포크이다. LLM(Large Language Model)기능을 사용자 인터페이스에 통합했다. 개인적인 취향으로는 Active bar가 왼쪽 사이드에 위치하지 않는게 아쉽긴 하다. (이건 익숙해지면 되니까…)

Cursor는 무료와 유료 구독이 있고, 현재 회사의 지원으로 비즈니스 구독 모델을 사용중이다. Cursor는 개발자가 IDE 환경과 LLM 사이의 상호 작용하는 방식을 혁신하고자 한다. 실제로 사용해보면 코딩 경험이 꽤 좋고, 재미가 생긴다.

이런 기능은 인지적 부하를 줄이도록 해주며, 개발을 가속화하기 위한 Concept이라고 생각한다. Cursor를 사용하면 브라우저에서 검색하거나 ChatGPT에서 질문하고 코드를 복사하여 붙여넣을 필요가 없다.

이제 주요 특징을 살펴보자.

탭 완성

탭 완성 기능은 자동 완성과 다르게 코드를 예측하고 권장되는 코드를 탐색하는데 도움이 된다. 간단하게 탭을 누르면 된다. 옆에서 숙련된 개발자가 다음 코드를 언급해주는 것과 비슷하다.

일반적으로 대화 방식의 인터페이스에 주로 의존하는 것과 다르게, Cursor의 탭 완성 기능은 개발자의 작업 흐름을 자연스럽게 확장해주는 느낌이다.

맥락을 이해하고 있으며, 다음 코드를 추천해주는 것이 생각보다 똑똑하다.

인라인 편집

인라인 편집은 코드 수정을 위한 채팅 기반 인터페이스를 제공한다. 코드 블록을 선택하고 AI가 개선 사항이나 리팩토링을 제안하기에 다른 관점에서 도움을 받을 수 있다. 코드를 선택하고 Cmd/Ctrl-K을 누르면 기존 코드의 컨텍스트 내에서 변경 사항을 제안한다.

Diff 뷰를 생성하여 Accept 전에 제안된 수정 사항을 즉시 시각화할 수 있다. 이 기능은 특히 작은 코드 세그먼트를 구현하거나 특정 기능 내에서 사소한 리팩토링 작업을 실행하는데 유용하다.

채팅

채팅을 통해 개발자는 코드에 대해 AI와 논의를 할 수 있고, 복잡한 리팩토링 시나리오를 시뮬레이션 해 볼 수 있다.

AI와 “페어 프로그래밍”을 하면서 코드에 대한 전체 맥락을 이해할 수 있다. 또한 특정 파일에 태그를 지정하고 질문을 할 수 있다.

채팅 사이드바는 더 포괄적인 상호작용을 위한 대화 공간이다. Cmd/Ctrl-L 을 누르면 AI와의 대화를 위한 공간을 제공한다.

Composer

이건 정말 강력한 기능이다. 여러 파일에 걸쳐 diff을 생성하고 개발자가 체계적으로 변경 사항을 보면서 승인을 할 수 있는 인터페이스다.

여러 파일에 걸쳐 순차적으로 수정 사항을 검토하고 적용하기 위한 체계적인 워크플로우를 제공한다. 또한 사용자는 모델을 변경할 수 있다. 참고로 나는 Claude 3.5 Sonnet 모델을 사용한다.

결론

IDE에 AI를 통합하는 것은 매우 훌륭한 작업이라고 생각한다. Text를 다루는 것은 LLM이 잘하는 일이고 코딩은 그저 “텍스트” 데이터라고 볼 수 있기에 코딩에 엄청난 영향을 미칠 것으로 생각된다. 당분간은 인간의 작업을 도와주고 개선시켜주는 도구로써 활용하는 것으로 생각하고 있다. 아마도 인간을 대체한다는 목표보다는 개선 관점에 더 발전할 것이다.

Cursor를 사용하는 것은 나뿐만 아니라 주변 동료들에도 엄청난 생산성 향상을 가져다주었다. Cursor를 이용하여 MVP를 만들기전까지는 예상하지 못했던 일이었는데, 상당한 코딩 경험이 있는 개발자분들께는 추천하고 싶다. 주니어 개발자의 경우는 AI를 써도 나쁘진 않지만, 본인 생각과 경험도 매우 중요하기에 학습 경험을 방해하지 않는 선에서 사용했으면 좋겠다.

어제인가? Okky에서 생성형 AI와 주니어 개발자 채용 관련 인터뷰 요청이 있었다. 아직 인터뷰를 진행 하진 못했지만 생각 일부를 정리해본다.

“프로그래밍” 이라는 용어는 실제로는 공통된 목표를 향해 나아가는 몇 가지 활동이다. 즉, “컴퓨터”가 특정 프로세스를 시뮬레이션하도록 하는 것이다. “프로그래밍”은 아이디어를 인간 중심 언어에서 기계 중심 언어로 번역하는 과정이며, 이것은 다시 기계어로 번역된다.

사람들이 컴퓨터로 하기를 원하는 대부분은 누군가의 머릿속에 있다. 이를 꺼내기 위해서는 “분석”이 필요한데, 누군가를 인터뷰하여 프로세스화 하는 것과 비슷하다. 혹은 시니어 개발자가 설계 문서를 작성하는 것과 같다.

아마도 이 관점에서 AI는 코딩 부분을 대부분 사라지게 할 것이라고 생각한다. 아쉽지는 않다. 더 창의적인 일에 몰두 할 수 있기 때문이다. 이유는 코딩은 “프로그래밍” 프로세스에서 가장 비효율적인 부분이라고 생각하기 때문이다. 아이디어 혹은 로직을 코드로 표현하는 것은 식물을 키우는 과정과 비슷하기 때문이다. 이 작업은 꽤 지루하기도 하고, 반복되는 부분에서는 즐겁지 않다.

AI에게 무엇을 할지 알려주는 일은 지금도 어느 정도는 인간의 몫이고, 적어도 소프트웨어를 전공한 사람들이 이 일을 하는데 가장 적합하다고 생각한다. AI는 컴퓨터가 우리가 원하는 것을 시뮬레이션하도록 하는 전반적인 프로세스를 변화시킬 것이고, “코딩” 부분에서 인간의 역할은 점점 작아질 것이고, “분석” 부분은 크게 변화할 것이라고 생각한다.

물론, AI가 올바른 코드를 생성했는지는 사람이 보긴해야 한다. AI가 생성한 코드를 신뢰만 하고, 코드가 잘못되었는지를 이해하지 못하면 문제가 발생할 수 있다.

주변 동료들의 이야기를 언급하며, 글을 마친다.

“룰 세팅하고, 요구 사항을 명확히하여 지시하니, 생각보다 훌륭한데요?”

“얘는 쉬지도 않고, 불만도 없어요.”

“제가 힌트를 주니깐, 동의하며 바로 이해하는데요? 재미가 있어요.”

“상황에 따라, 주니어 개발자 혹은 시니어 개발자가 옆에 있는 느낌이에요.”

“레거시 인터페이스에 대해서는 아직 약한것 같아요. 한편으로는 컨트롤 및 분석 역할을 제가 할 수 있어서 다행이에요.”

1/03/2025

오류를 재현할 수 없나요?

 

“제 컴퓨터에서는 동작하는데요?”라는 것은 웃음거리가 될 수 있지만, 개발자 세계에서 많이 퍼진 태도를 의미하기도 한다. 우리는 책임을 지고 문제를 찾아야 한다.

그렇다면 버그가 발생하면 어떻게 해야 할까? 일반적으로는 두 가지 접근 방식이 있다. 처음에는 문제가 발생하는 환경을 복제해야 한다. 운영 스테이지가 아닌 QA, Dev 등 비슷한 환경이 구성되어 있어야 한다. 아니면 원격 디버깅을 사용해야 한다.

프로젝트를 진행하면서 사용자가 보고한 버그를 재현하려고 했던 경험이 있다. 환경을 비슷하게 맞췄지만 버그가 재현되지 않았다. 결국에는 사용자와 커뮤니케이션을 하면서 네트워크 환경이 다르다는 것을 인지하고 네트워크 스로틀링을 통해 확인하였다.

다른 버그에서도 재현이 되지 않은 상황이 있었다. Datadog을 통해 사용자가 특정 UI에서 다른 패턴으로 이용하는 것을 알아챘다. 그대로 해보니 버그가 재현되었다.

이런 상황에서는 사용자 행동을 최대한 분리하는 것이 중요하다. 사용자 패턴이 녹화된 영상을 통해 사용자 행동을 검증하는 것이 도움이 될 수 있다. (Datadog 사랑해요!)

복제된 환경에서 미묘한 차이점을 이해하는 것이 핵심이고, 버그를 재현할 수 있는 방법을 찾아야 한다.

그러나 장애물이 존재할 수 있다. 장애물이란 문제를 보고하는 사람일 수도 있고, 개발자일 수도 있다. 혹은 화가 난 사용자일 수도 있다.

그나마 다행인 점은 컨테이너 기술의 출현으로 균일한 환경을 쉽게 갖출 수 있다는 점이다. 하지만 미묘한 차이는 존재한다. 환경에 상당한 영향을 미치는 네트워크, 데이터 규모와 같은 요소가 있다. 대규모 환경에서 초당 10,000개의 요청이 있을 때만 나타나는 문제를 어떻게 재현할 수 있을까? 결국 모니터링 도구를 잘 이용해야 한다. 모니터링 도구는 이러한 상황을 관리하고 관찰하는데 매우 유용할 수 있다.

로깅도 애플리케이션의 중요한 기능이다. 여러 케이스를 디버깅하는데 매우 정확한 도구이다. 로깅은 모니터링 도구와 마찬가지로 사전에 준비되어야 한다. 로깅을 하지 않는 곳은 디버깅이 되지 않기 때문이다. 이상적으로는 테스트를 잘 수행하여 이런 상황이 발생하지 않아야 한다. 그러나 실제는 그렇지 않다.

오류를 파악하기 어려운 경우에는 동시성 관련 문제가 발생할 가능성이 매우 높다. 문제 현상이 일관되지 않을 경우에는 연관된 스레드를 확인하고 예상대로 동작되는지 확인해야 한다. 단일 스레드를 사용하여 특정 메서드에 동시성 경쟁 문제가 있는지 확인해야 한다.

이렇게라도 찾으면 다행이지만, “포기” 해야 하는 경우도 발생한다. 문제를 일관되게 재현하는 것이 불가능하다는 것을 받아들여야 할 때가 올 수도 있다. 이럴 경우에는 문제를 좁히기 위해 로깅을 추가하는 것이 중요하다. 해당 오류가 다시 발생하면 분석할 정보가 많아지기 때문이다.

결국, 오류 해결은 끈기와 끊임없는 학습 및 경험에 관한 것이다. 디버깅 경험을 통해 어떻게 개선하고 성장할 수 있는지 이해하는 것이다.

“제 컴퓨터에서는 잘 동작하는데요?”라는 것은 소프트웨어 개발 세계에서 종종 목격된다. 이 업종에 종사하는 사람들은 오류에 대한 소유권을 가져야 하며, 사용자 환경과 행동을 최대한 비슷하게 복제하려고 노력해야 한다. 명확하게 커뮤니케이션을 해야 하며, 모니터링 도구 및 로깅을 통해 원인을 판단해야 한다.

그러나 네트워크, 데이터 규모의 차이로 인해 디버깅에 영향을 미칠 수 있다. 어떤 경우에는 오류가 일관되게 재현되지 않을 수도 있다. 이런 경우에는 잠재적 원인에 대해 가정을 할 수 있어야 하고, 가정을 재현하는 테스트 케이스를 만들고, 향후 발생했을 경우에 더 많은 정보를 얻기 위해 로그를 추가해야 한다.

디버깅은 끈기와 적응력이 필요한 학습 경험이며, 모든 개발자의 성장에 필수적이다.

오류가 없는 것이 가장 좋지만, 오류를 만나게 되면 성장을 위한 발판으로 삼았으면 좋겠다.

12/18/2024

RabbitMQ와 Kafka를 사용하는 경우

 

어제 테크 미팅 때, RabbitMQ와 Kafka에 대한 이야기가 나왔다.

본 글에서는 두 가지 기술을 더 광범위한 관점에서 생각해보고, 두 시스템이 제공하는 기능에 초점을 맞췄다. 이를 통해 어떤 시스템을 언제 사용하는게 좋은지 결정을 내리는데 도움이 되었으면 좋겠다.

웹 검색을 했을 때, 일부 글은 RabbitMQ보다 Kafka가 더 뛰어나다고 주장하고, 다른 글에서는 그 반대인 경우가 많다. 그렇기 때문에 서로 혼선이 오는 것 같다.

RabbitMQ와 Kafka 중 무엇을 선택할지에 대한 결정은 프로젝트의 요구 사항에 따라 달라지며, 적절한 시나리오에서 둘 다 사용해 본 경우에만 비교가 가능하다는 것을 아는 것이 중요하다.

두 시스템 모두 큐 또는 토픽을 통해 생산자와 소비자 간 메시지를 전달한다. 메시지에는 모든 종류의 정보가 포함될 수 있다. 예를 들어서 웹사이트에서 발생한 이벤트 혹은 다른 애플리케이션에서 이벤트를 트리거하는 메시지가 될 수 있다.

RabbitMQ와 Kafka 같은 시스템은 서로 다른 구성 요소를 연결하고, 데이터를 전달하는 용도로 사용될 때 이상적이다.


비교해보기

RabbitMQ는 AMQP, MQTT, STMOP 등과 같은 다양한 프로토콜을 지원하는 메시지 브로커이다. 높은 처리량을 처리할 수 있다.

Kafka는 높은 유입 데이터 스트림과 메시지 재생에 최적화된 메시지 버스이다. 애플리케이션이 디스크에서 스트리밍된 데이터를 처리하고 다시 처리할 수 있는 내구성 있는 메시지 브로커로 볼 수 있다.

RabbitMQ는 2007년에 출시되었고, Kafka는 2011년에 출시되었기에, 2024년이 지금 시점에서는 둘 다 신뢰할 수 있는 성숙한 시스템으로 인지할 수 있다.

그리고 세월이 흘러서 RabbitMQ도 Stream을 지원하기 시작했다. 브로커로서 RabbitMQ의 메시지는 소비되고 확인되면 큐에서 삭제된다. 이런 특성으로 인해 데이터를 장기로 보관해야 하는 지속성이나 메시지를 다시 재생해야 하는 시나리오에는 적합하지 않았다. 그러나 RabbitMQ v3.9에서는 모든 것이 바뀌었다.

Stream Queues는 RabbitMQ v3.9에 도입되었다. 지속적이고 복제되며, 기존 큐와 마찬가지로 소비자가 읽을 수 있도록 메시지를 버퍼링한다. 그러나 Streams는 아래 측면이 기존 큐와 다르다.

  • 생산자가 메시지를 쓰는 방법
  • 소비자들이 메시지를 읽는 방법

Stream에 쓰여진 메시지는 지울 수 없고, 읽을 수만 있다. RabbitMQ에서 Stream의 메시지를 읽으려면 하나 이상의 소비자가 구독해야 하고 원하는 횟수만큼 동일한 메시지를 읽는다.

위 기능은 RabbitMQ의 스트림 큐를 Kafka와 유사한 기능을 찾는 사용자에게 매력적인 옵션으로 만든다.

RabbitMQ의 Streams에 대한 설명을 여기까지 하고 본론으로 돌아가서 두 가지 기술을 바라볼때, 가장 중요한 점은 “언제 Kafka를 사용하고, 언제 RabbitMQ를 사용해야 하는가?” 이다.

메시지 처리 (메시지 재생)

기존 RabbitMQ 큐는 소비자가 메시지를 수신할 때까지만 메시지를 저장했지만, Streams는 이를 대폭적으로 변경했다.

메시지 재생에 관해 RabbitMQ와 Kafka는 모두 같은 방식으로 처리한다. Kafka와 RabbitMQ Streams에 전송된 데이터는 지정된 보관 기간(기간 또는 크기 제한)이 지날 때까지 저장된다. 메시지는 보관 기간/크기 제한을 초과할 때까지 큐에 남아 있으므로 소비된 메시지는 제거되지 않는다. 대신 여러 번 재생되어 소비될 수 있다.

RabbitMQ와 Kafka에서 제공하는 리플레이에 대한 기능은 소비자에게 버그가 있어서 일부 또는 모든 메시지를 다시 처리해야 하는 경우다. 이 경우외에 이벤트를 여러 번 재생하는 것은 바람직하지 않다.

규약

RabbitMQ는 AMQP, MQTT, STOMP 등과 같은 여러 표준화된 프로토콜을 지원한다.

Kafka는 애플리케이션과 클러스터 간 통신을 위해 TCP/IP 기반 자체 프로토콜을 사용한다. 이 프로토콜은 간단히 제거하여 교체할 수 없다. 이것만 쓰기 때문이다.

따라서, RabbitMQ가 다양한 프로토콜을 지원하기에 다양한 시나리오에서 사용할 수 있다.

라우팅

RabbitMQ의 가장 큰 이점은 메시지를 유연하게 라우팅 할 수 있다는 것이다. 다이렉트 또는 정규 표현식 기반 라우팅을 사용하면 추가 코드 없이도 메시지가 특정 대기열에 도달할 수 있다.

RabbitMQ는 다이렉트, 토픽, 팬아웃 및 헤더 교환의 라우팅 옵션이 있다.

Kafka는 라우팅을 지원하지 않는다. Kafka 토픽은 변경 불가능한 순서로 메시지를 포함하는 파티션으로 나뉜다. RabbitMQ의 라우팅을 대체하기 위해 소비자 그룹과 영구 토픽을 사용할 수 있다. 모든 메시지를 해당 토픽으로 보내지만 소비자 그룹이나 다른 오프셋에서 구독하도록 할 수 있다.

오프셋은 각 메시지에 부여된 고유 ID로, 메시지 로그에서 메시지의 순서를 나타낸다.

Kafka 스트림을 사용하면 이벤트를 토픽에 동적으로 라우팅하는 것을 만들 수 있지만, 이 기능은 기본 기능이 아니다.

메시지 우선 순위

RabbitMQ는 우선순위 대기열이라는 것을 지원하는데, 이는 대기열에 다양한 우선순위로 설정할 수 있다는 것을 의미한다. 각 메시지의 우선순위는 게시될 때 설정할 수 있다.

우선순위 대기열은 언제 사용할 수 있을까? 예를 들면, 어떤 데이터를 매일 백업을 하는데 수천 개의 백업 이벤트가 순서 없이 추가되는 상황에서, 새 백업 이벤트를 우선순위를 높여서 먼저 처리하게 하고 싶을때 사용할 수 있다.

Kafka는 메시지를 우선순위 수준으로 보내거나 우선순위 순서대로 전달할 수 없다. Kafka의 모든 메시지는 수신 순서대로 저장되고 전달된다.

확인(Commit or Confirm)

확인이라는 단어의 의미는 전송되거나 메시지가 수신되었음을 나타내기 위한 신호이다.

Kafka와 RabbitMQ는 게시된 메시지가 브로커에 안전하게 도달했는지 확인하기 위해 생산자 확인 기능을 지원한다.

노드가 소비자에게 메시지를 전달할 때, 소비자가 메시지를 수신한 것으로 간주해야 하는지 결정해야 한다.

RabbitMQ는 메시지가 전송되면 전달된 것으로 간주하거나, 메시지를 수신한 후 소비자가 수동으로 확인할 때까지 기다릴 수 있다.

Kafka는 파티션의 각 메시지에 대한 오프셋을 유지한다. 커밋된 위치는 저장된 마지막 오프셋이다. Kafka를 사용하는 소비자는 오프셋을 주기적으로 자동 커밋하거나 커밋된 위치를 수동으로 제어하도록 선택할 수 있다. (Kafka에서 메시지 소비에 대해 추적하는 방식은 버전마다 다르다.)

RabbitMQ는 메시지를 처리하지 못할 때 메시지를 nack 할 수 있다. 메시지는 마치 새 메시지인 것처럼 원래 있던 큐로 반환된다. 이는 소비자 측에서 일시적인 오류가 발생한 경우에 유용하다.

대기열 처리

RabbitMQ의 기존 큐는 비어 있을 때 가장 빠르다. 그러나 RabbitMQ Streams와 Kafka는 모두 대량의 메시지를 보관하고 배포하도록 설계되었다.

RabbitMQ의 기존 큐는 “지연 모드”를 사용할 수 있다. 지연 큐는 메시지가 자동으로 디스크에 저장되어 메모리 사용량을 최소화하지만 처리량의 시간을 늘리는 큐이다. 지연 큐는 더 나은 예측 성능을 가진 안정적인 클러스터를 만든다. 한 번에 많은 메시지를 보내는 경우 혹은 소비자가 게시자의 속도를 지속적으로 따라가지 못할 것이라고 생각되는 경우 지연 큐를 활성화 하는 것이 좋다.

스케일링

스케일링은 시스템의 용량을 늘리거나 줄이는 과정을 의미한다. RabbitMQ와 Kafka는 다양한 방식으로 스케일링을 할 수 있으며, 소비자 수, 브로커의 파워를 조정하거나 시스템에 노드를 추가할 수 있다.

소비자 확장

RabbitMQ에서 소비할 수 있는 것보다 더 빨리 메시지가 게시되면 대기열이 커지게 되고, 많은 메시지가 생겨 결국 RabbitMQ의 메모리가 소진될 수 있다. 이 경우 메시지를 처리(소비)하는 소비자의 수를 확장할 수 있다. RAbbitMQ의 각 대기열에는 많은 소비자가 있을 수 있으며 이러한 소비자는 모두 대기열의 메시지를 소비하기 위해 “경쟁” 할 수 있다. 메시지 처리가 모든 활성 소비자에게 분산되기에 RabbitMQ에서 확장 또는 축소는 소비자를 추가하고 제거하기만 하면 된다.

Kafka에서 소비자를 분산하는 방법은 토픽 파티션을 사용하는 것이다. 이렇게 되면 그룹의 각 소비자는 하나 이상의 파티션을 사용한다. 파티션 매커니즘을 사용하여 각 파티션에 비즈니스 키(사용자ID 등)에 따라 다른 메시지 세트를 보낼 수 있다.

브로커 확장

RabbitMQ는 수평 확장이 항상 더 나은 성능을 제공하지 않는다. 가장 좋은 성능 수준은 수직 확장으로 달성된다. 수평 확장도 가능하지만, 노드 간에 클러스터링을 설정해야 하기에 설정 속도가 느려질 수 있다.

Kafka는 클러스터에 노드를 더 추가하거나 토픽에 파티션을 더 추가하여 확장할 수 있다. 이는 RabbitMQ가 해야 하는 것처럼 기존 머신의 CPU나 메모리를 추가하는 것보다 더 쉬울 수 있다.

로그 압축

RabbitMQ에는 없지만 Kafka에는 있는 기능이 로그 압축 전략이다. 로그 압축은 Kafka가 단일 토픽 파티션의 큐내에서 각 메시지 키에 대해 항상 마지막인 값을 유지하도록 보장한다. Kafka는 단순하게 메시지의 최신 버전을 유지하고 동일한 키를 가진 이전 버전을 삭제한다.

로그 압축은 Kafka를 데이터베이스로 사용하는 방법으로 볼 수 있다. 보존 기간을 “영구”로 설정하거나 토픽에서 로그 압축을 활성화하면 데이터가 영원히 저장된다.

압축된 로그는 충돌이나 장애 후 시스템을 복원해야 할 때 유용하다.

모니터링

RabbitMQ는 웹 브라우저에서 서버를 모니터링할 수 있다. 대기열, 연결, 채널, 교환, 사용자 및 사용자 권한을 브라우저에서 처리할 수 있으며 메시지 속도도 모니터링하고 메시지를 수동으로 보내고 받을 수 있다.

Kafka는 모니터링을 위해 오픈소스 툴을 사용해야 한다.

Push와 Pull

RabbitMQ에서는 메시지를 소비자에게 푸시한다. 소비자가 받을 수 있는 여력을 보장하기 위해 사전에 제한을 구성하는 것이 중요하다. (소비자가 처리하는 것보다 메시지가 빠르게 갈 경우) 소비자는 RabbitMQ에서 메시지를 풀링할 수 있지만 권장하지 않는다.

Kafka는 풀 모델을 사용한다. 소비자는 주어진 오프셋에서 메시지를 요청한다. (소비자가 처리하는 것보다 메시지가 빠르게 갈 수 없는 장점)

라이센스

RabbitMQ는 2023년에 브로드컴의 일부가 되었다. 그러나 소스 코드는 모질라 퍼블릭 라이센스로 공개되어 있다. 라이센스는 변경된 적이 없다.

Kafka는 링크드인에서 만들었다. 2011년에 Apache 재단으로 넘어갔다. 따라서 Kafka는 Apache 2.0 라이센스의 적용을 받는다.

두 라이센스 모두 무료 오픈 소스 라이센스이다.

복잡성

개인적인이긴 하지만 RabbitMQ가 더 쉽다. 그 이유는 Kafka의 경우는 토픽/파티션/메시지 오프셋 등과 같은 더 많은 개념을 이해해야 한다. 그래서 더 많은 복잡성이 있다.

Kafka 생태계

Kafka는 단순한 브로커가 아니라 스트리밍 플랫폼이다. 그래서 Kafka와 쉽게 통합할 수 있는 많은 도구가 존재한다. 예를 들어 Kafka Core, Kafka Streams, Kafka Connect, Kafka REST Proxy 등이다. 그러나 대부분 도구는 Confluent에서 제공되며 Apache의 일부가 아니다.

도구가 많다는 점은 연결되는 시스템을 구성할 수 있다는 장점이 있다.

Kafka REST Proxy는 클러스터에서 메타 데이터를 수신하고 간단한 REST API를 통해 메시지를 생성하고 소비할 수 있도록 제공한다.

Kafka Connect는 다른 시스템을 Kafka와 통합할 수 있다.

일반적인 사용 사례

지금까지는 각 시스템이 무엇을 할 수 있고, 못하는지에 대한 얘기를 했다. 이제는 어떤 시스템을 사용할지 생각하고 결정을 내리는 방법에 대해서 설명하려고 한다.

RabbitMQ의 사용 사례

일반적으로 단순하고 전통적인 Pub-Sub 메시지 브로커를 원한다면 RabbitMQ가 확실한 선택이다. 채널 및 큐를 통해 통신을 처리하고 스트리밍을 옵션으로 추가하는 것이 요구 사항이라면 RabbitMQ를 선택했을 것이고 초보자에 더 친화적인 옵션이라고 생각할 수 있다. 그리고 Streams 지원이 있다.

복잡한 라우팅

RabbitMQ는 복잡한 라우팅에서 빛을 발한다. 다른 메시징 시스템과 달리 메시지 라우팅 프로세스를 완벽하게 제어할 수 있다. 콘텐츠 유형, 메시지 우선 순위 및 비즈니스 로직과 같은 여러 조건에 따라 메시지를 라우팅하도록 시스템을 구성할 수 있다.

우선 순위 대기

RabbitMQ는 특정 메시지를 다른 메시지보다 우선시할 수 있는 기능인 우선 순위 큐를 지원한다. 우선 순위 큐를 사용하면 시스템에 부하가 많을 때에도 중요한 메시지가 먼저 처리되도록 할 수 있다.

다중 프로토콜

RabbitMQ는 여러 프로토콜을 지원하기 위해 기능을 확장하고 있다. 현재 AMQP, MQTT, STOMP를 지원한다. 그러나 RabbitMQ의 아키텍처는 AMQP를 위해 설계되었기에 다른 프로토콜을 효율적으로 실행하는데에는 어려움을 겪을 수 있다.

Kafka의 사용 사례

일반적으로 스트리밍 데이터를 저장, 읽기(다시읽기), 분석하기 위해 순수하게 설계된 것을 원한다면 Kafka를 사용해야 한다. 감사를 받는 시스템이나 메시지를 영구적으로 저장해야 하는 시스템에 이상적이다.

즉, 로그 처리, 스트림 처리, 분산 시스템에 특히 유용하다.

높은 처리량

Kafka의 가장 주목할 만한 특징은 대량의 데이터를 처리할 수 있는 능력이다. 초당 수십만 개의 메시지를 처리하도록 설계되어 실시간으로 대량의 데이터를 처리해야 하는 애플리케이션에 탁월한 선택이다.

로그 처리 및 스트림 처리

Kafka는 로그 처리 및 스트림 처리에도 적합하다. Kafka는 내장된 로그 저장 시스템을 통해 다양한 소스의 로그 데이터를 효율적으로 저장하고 처리할 수 있다. 또한 스트림 처리를 지원하여 데이터가 도착하는대로 실시간으로 처리할 수 있다.

분산 시스템

Kafka는 분산 시스템에 탁월하다. 분산 아키텍처를 통해 수평적으로 확장하여 증가된 데이터 부하를 수용할 수 있다. 또한 일부 서버가 실패해도 데이터가 안전하게 보호되도록 한다.


어떤 상황에서 어떤 시스템을 쓸 것인지, 현명하게 결정해야 한다.