코드를 딱 열었을 때 코드가 깔끔하고 일관적이며 꼼꼼하다고 감탄하며 질서정연하다고 탄복하며 모듈을 읽으며 두눈이 휘둥그래지는 전문가가 잤다는 인상을 심어주는 코드가 되었으면 좋겠다. 코드가 술에 취해 짜놓은 듯 어수선해 보인다면 프로젝트의 다른 측면도 똑같이 무성의한 태도로 처리했을거라 생각할 것이다. 프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야한다. 코드 형식을 맞추기 위해 간단한 규칙을 정하고 그 규칙을 따라야 한다. 팀이라면 팀이 합의하여 규칙을 정하고 그 규칙을 모두가 따라야 한다. 규칙을 자동으로 적용하는 도구도 활용한다. 코드 형식은 중요하다. 적절한 행 길이를 유지하라 (세로 형식 맞추기) 대부분의 자바 소스 파일의 크기는 어느 정도일까? JUnit, FitNesses, Time and..
멱등성이란? 전달 신뢰성으로 여러번 연산을 수행하더라도 동일한 결과를 나타내는 것을 뜻한다. 따라서 이러한 멱등성 프로듀서는 동일한 데이터를 여러번 전송해도 카프카 클러스터에 단 한번만 저장되게 된다. 반면에, 기본 프로듀서의 동작 방식은 적어도 한번 전달(at least once delivery)를 지원한다. 여기서 적어도 한번 전달이란 프로듀서가 클러스터에 데이터를 전송하여 저장할 때 적어도 한번 이상 데이터를 적재할 수 있고 데이터가 유실되지 않음을 의미한다. 하지만 두 번 이상 적재할 가능성이 있으므로 데이터의 중복이 발생할 수 있다. 메시지 전달에는 아래와 같이 3가지의 경우가 존재한다. at least once: 적어도 한번 이상 전달 at most once: 최대 한번 전달 exactly o..
주석 나쁜 코드에 주석을 달지 마라. 새로 짜라. 주석은 필요악이다. 우리는 코드로 의도를 표현하지 못해서, 그러니깐 실패를 만회하기 위해 주석을 사용하는 것이다. 주석은 언제나 실패를 의미한다. 주석 없이는 코드로 자신을 표현할 방법을 찾지 못해 할 수 없이 주석을 사용한다. 따라서 주석은 반겨 맞을 것이 아니다. 주석을 엄격하게 관리해야 한다고도 한다. 그 의견도 맞지만, 코드를 깔끔하게 정리하고 표현력을 강화하는 방향으로, 그래서 애초에 주석이 필요없는 방향으로 에너지를 쏟아야 한다. 부정확한 주석은 아예 없는 주석보다 훨씬 더 나쁘다. 부정확한 주석은 독자를 현혹하고 오도한다. 진실은 한곳에만 존재한다. 그것이 바로 코드다. 코드만이 자기가 하는일을 진실되게 말한다. 코드만이 정확한 정보를 제공하..
컨슈머 애플리케이션 컨슈머가 poll()하는 코드 코드 실행 후 아래와 같이 프로듀서에서 메시지를 보내면 앱 실행 화면에서 응답을 확인할 수 있다. 실행중인 애플리케이션의 로그를 통해서도 확인이 가능하다. 동기 오프셋 커밋 컨슈머 poll() 메소드가 호출된 이후에 commitSync() 메소드를 호출함으로써 오프셋 커밋을 명시적으로 수행할 수 있다. commitSync()는 poll()로 받은 가장 마지막 오프셋을 기준으로 커밋을 하게 된다. 참고로, 동기 오프셋 커밋을 사용하는 경우 모든 레코드의 처리가 끝난 이후 commitSync()를 호출해야한다. 프로듀서에서 메시지를 보내면 정상적으로 메시지가 출력되고 커밋이 이뤄지게 된다. 오프셋 값은 kafka-consumer-groups 명령어로 특정 그..
참고사항 이 책의 저자는 객체지향 기본 설계 원칙(SOLID)를 정의한 사람이다. "이 책에서의 교훈이 절대적인 진리"다. 라고 저자는 말한다. (오브젝트 진영에서) 1장. 깨끗한 코드 프로그래밍이란, 기계가 실행할 정도로 상세하게 요구사항을 명시하는 작업이다. 따라서 코드를 자동으로 생성하는 시대가 다가오면서 프로그래머가 필요 없어질 것이란 말은 헛소리이다. 요구사항을 애매모하게 줘도 우리의 의도를 정확히 꽤뚫어 프로그램을 완벽하게 실행하는 기계는 불가능하다. 궁극적으로 코드는 요구사항을 표현하는 언어이다. 나쁜 코드를 짜는 이유는 상사의 기한에 대한 쪼임, 업무에 대한 지겨움, 업무가 밀려서 등등 다양한 이유가 있다. 하지만 이러한 코드로 인해 얽히고 설킨 코드를 '해독'해서 코드를 더해가야 하며 이..
컨슈머 프로듀서가 전송한 데이터는 브로커에 적재된다. 컨슈머는 이 적재된 데이터를 사용하기 위해 브로커로부터 데이터를 가져와서 필요한 처리를 담당한다. 예를 들어 마케팅 문자를 고객에게 보내는 기능이 있다면 컨슈머는 토픽으로부터 쌓여있는 고객 데이터를 가져와서 문자 발송 처리를 진행하게 된다. 컨슈머 내부 구조 Fetcher: 리더 파티션으로부터 레코드들을 미리 가져와서 대기하는 역할 poll(): Fetcher에 (이미)있는 레코드들을 리턴한다. ConsumerRecords: 처리하고자 하는 레코드들의 모음이다. 이때 처리된 레코드는 커밋으로 체크된다. 이 레코드에는 오프셋이 포함되어 있으므로 읽은 위치를 확인할 수 있게 된다. 따라서, 처리를 완료한 레코드에 대해서는 commit을 수행하여 처리한 레..
프로듀서 애플리케이션 개발 위 코드를 실행 시키면 실제 test 토픽에 testMessage 레코드가 쌓인것을 확인할 수 있다. 메시지 키를 가진 레코드를 전송하는 프로듀서 키값을 같이 확인하기 위해 --property옵션을 같이 넣어서 실행시켜준다. 키값 없이 보냈던 메시지의 키는 null로 나오고 그 외의 경우 같이 출력되는 것을 확인할 수 있다. 레코드에 파티션 번호를 지정하여 전송하는 프로듀서 파티션을 직접 지정하고 싶다면 토픽이름, 파티션 번호, 메시지 키, 메시지 값을 차례로 입력하여 보내면 된다. 특정 파티션 (3번)에 메시지를 보내고 컨슈머에서 해당 파티션의 메시지를 읽을 수 있다. 커스텀 파티셔너를 가지는 프로듀서 config에서 PARTITIONER_CLASS_CONFIG에 직접 작성한..
프로듀서 프로듀서 애플리케이션의 역할 카프카에 필요한 데이터를 선언하고 브로커의 특정 토픽의 파티션에 전송한다. 데이터를 전송할 때 리더 파티션을 가지고 있는 브로커와 직접 통신한다. 브로커로 데이터를 전송할 때 내부적으로 파티셔너, 배치 생성 단계를 거친다. 프로듀서 내부 구조 ProducerRecord: 프로듀서에서 생성한 레코드, 오프셋은 미포함 send(): 레코드 전송 요청 메소드 Partitioner: 어느 파티션으로 전송할 지 지정하는 파티셔너이다. Accumulator: 배치로 묶어서 전송할 데이터를 모으는 버퍼이다. send()를 해도 바로 보내는것이 아니라 Accumulator내 배치의 임계치까지 데이터가 쌓이면 그때 카프카 클러스터와 TCP 통신하여 데이터를 전송하게 된다. 이러한 배..
카프카 CLI tool 토픽 관련 명령을 실행할 때 필수 옵션과 선택옵션이 존재한다. 해당 값들이 어떻게 설정되어있는지, 어떻게 설정할지 확인 후 CLI 툴을 사용하자. zookeeper-server.start.sh / kafka-server-start.sh 카프카 실행을 로컬에서 진행할 것이므로 로컬 통신을 위한 호스트를 지정해주자. 로그와 인덱스 등의 파일을 저장하기 위한 위치도 지정해준다. etc/hosts 파일에 localhost 주소에 대한 "my-kafka"라는 별칭을 추가해준다. kafka-topics.sh 카프카 토픽에 대해 CLI를 진행해보자. kafka-topcis.sh를 통해 토픽 생성이 가능하다. 카프카 토픽을 생성 시 디폴트 값으로 설정된 것을 확인해 볼 수 있다. 다음과 같이 처..
1. 카프카 역사와 미래 프로듀서 -토픽 - 컨슈머 구조 토픽 내 여러 파티션이 존재하며, 프로듀싱은 하나의 파티션에만 쌓인다. 파티션은 큐 구조로 FIFO로 쌓이지만 컨슈밍하여도 제거되지 않는다. 읽은 위치는 commit으로 기록한다. 높은 처리량 프로듀서 → 브로커, 브로커 → 컨슈머로 데이터를 전송할 때 묶음 단위 전송으로 속도를 개선 여러 파티션에 분배하고, 파티션 수 만큼 컨슈머를 늘림으로서 병렬처리를 하여 시간당 데이터 처리량 개선 가능 확장성 특정 이벤트가 몇건 들어올 지 모를 때 가변적으로 대응할 수 있다 데이터를 저장하고 있는 곳이 브로커이며, 사용량이 적고 많은에 따라 브로커 scale-in/out이 가능 영속성 다른 메시징 플랫폼과 다르게 전송받은 데이터를 메모리가 아닌 파일 시스템에..
저번 포스팅에 이어서 Spring Security와 Jwt을 사용하여 회원 인증/인가 시스템을 만들어 보겠다. Spring Security를 사용하게 되면 전달받은 JWT를 Filter를 통해 Authorization(인가), Authentication(인증) 을 처리하게 된다. 이를 위해서 User 정보를 Jwt의 Payload에 Claim들을 넣고, 꺼내서 처리할 수 있는 시스템을 만들면 된다. 우리가 갖고 있는 User를 그대로 클레임으로 넣고 꺼내서 처리하기에는 모든 User 모델이 제각각일테니 이를 처리하기 위한 공통의 인터페이스가 존재한다. UserDetails Interface이며 이를 implements한 User 객체를 새로 만들어서 사용하면 된다. Member implements Use..
스프링 부트로 프로젝트를 진행할 때 필요한 기술들이 많아지면서 기본 틀을 잡는데도 많은 공수가 들어가며 환경설정에 너무 많은 시간이 들게 되었다. 이에 미리 프로젝트를 위한 구조를 만들고 실행 가능한 이미지를 만들어서 도커에 올려 놓으려고 한다. 진행할 목차에 대해 간단히 정리하면 필요 라이브러리 설치 Spring Data JPA, Spring Data Envars, QueryDSL 적용 API 사용 및 테스트를 위한 기본 설정 REST API / GraphQL (DGS) JWT 사용을 위한 기본 설정 로그인 / 로그아웃 구현 FLYWAY를 통한 기본 테이블 생성 및 데이터 삽입 Redis를 이용한 캐시 AOP 적용 도커 이미지 생성 후 업로드 위와 같은 순서로 적용해보고자 한다. 사용 기술 언어 / 프..
- Total
- Today
- Yesterday