Zayson
A to Zayson!
Zayson
전체 방문자
오늘
어제
  • 분류 전체보기 (132)
    • Computer Science (20)
      • Network (4)
      • DB (12)
      • OS (4)
    • Algorithm (32)
      • 완전탐색(Brute-Force) (3)
      • 그리디(Greedy) (6)
      • 투포인터(Two-Pointer) (1)
      • 그래프(Graph) (5)
      • BFS & DFS (9)
      • 구현, 시뮬레이션(Implementation) (5)
      • 다이나믹 프로그래밍(DP) (3)
    • Backend (51)
      • Spring Boot (19)
      • JPA (16)
      • Kafka (2)
      • Java (13)
      • Kotlin (1)
    • DevOps (1)
      • Jenkins (5)
      • Oracle Cloud Infrastructure (1)
      • Kubernetes & Docker (1)
    • Trouble Shooting (3)
      • JPA (1)
      • Spring Boot (2)
    • 회고 (5)
      • 엔빵 프로젝트 포스트 로드맵 (1)
      • 2022년 (4)
    • Kafka (7)
      • Kafka (5)
      • Kafka Connect (2)
    • 기술 서적 (6)
      • 데이터 중심 애플리케이션 설계 (3)
      • 개발자가 반드시 정복해야할 객체 지향과 디자인 패턴 (2)
      • 가상 면접 사례로 배우는 대규모 시스템 설계 기초 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

태그

  • 프로그래머스
  • 그리디
  • BFS
  • CS
  • 엔빵프로젝트
  • dfs
  • JPA
  • 나 혼자 스프링부트!
  • Java
  • 관계형 데이터베이스 실전 입문
  • 구현
  • 완전탐색
  • 라이브스터디
  • kafka
  • Computer science
  • Kafka Connect
  • 백준
  • SpringBoot
  • spring boot
  • Backend

최근 글

티스토리

hELLO · Designed By 정상우.
Zayson

A to Zayson!

Kafka를 이용해 Producer/Consumer 맛보기! - Configuration
Backend/Kafka

Kafka를 이용해 Producer/Consumer 맛보기! - Configuration

2022. 5. 6. 00:46

토이 프로젝트를 진행하던 도중 API Gateway를 도입하게 되면서 기존 회원 API 서버 내 회원 서비스에 구현되있는 소셜 로그인 및 회원 가입 기능과 JWT 엑세스 토큰 및 리프레시 토큰을 발급해주는 기능을 인증 서버내 회원 서비스로 따로 빼게 되었다.

 

이 때, 발생한 문제점이 있다.

현재 토이 프로젝트는 소셜 로그인을 이용하지만 추가적인 정보가 필요하기 때문에 소셜 로그인 이후 해당 서비스에 처음 로그인 한 경우 (서비스에 가입되지 않은 상태)라면 추가적인 회원 정보 및 추천인과 관심 OTT 서비스를 등록해야 한다.

 

여기서 추가적인 회원 정보는 인증 서버 내 회원 서비스에서 사용하는 간단한 회원 가입 로직을 이용하면 되지만, 가입 시 입력한 추천인에게 포인트를 적립(Optional)해주거나 회원이 관심있는 OTT 서비스를 등록(Optional)하는 로직을 인증 서버의 역할로 가져가기엔 회원 API 서버와 인증서버간 경계 구분이 모호해진다는 결론이 나왔다.

 

이러한 문제점을 어떻게 해결할지 고민하던 도중 Kafka를 이용해 인증 서버 에서 회원 API 서버로 간단한 메세지 데이터를 전달해 포인트 적립 로직과 관심 OTT 서비스 등록 로직을 회원 API 서버 내 포인트 서비스와 관심 OTT 서비스에서 처리하도록 구현하기로 결정했다.

⛳ 로드맵

  1. Kafka 의존성 추가 및 Producer/Consumer Java Configuration 설정
  2. Producer/Consumer 구현 및 기존 로직과 비교

기본 설정

현재 프로젝트는 Gradle을 사용한다.

build.gradle 파일에 Spring kafka 의존성을 추가한다.

// Kafka 의존성 추가
dependencies {
	implementation 'org.springframework.kafka:spring-kafka'
	testImplementation 'org.springframework.kafka:spring-kafka-test'
}

Kafka관련한 설정을 application.properties로 관리하지 않고 Java Configuration를 이용해서 필요한 정보들만 설정했다.

application.properties는 Kafka의 Bootstrap Server의 host와 port를 @Value로 받아오기 위해 간단하게 작성해주었다.

# Kafka의 Bootstrap Server는 일반적으로 9092번 포트를 이용한다. 
kafka.host=localhost
kafka.port=9092 

Producer Configuration

인증 서버에서 회원 API 서버로 메세지를 보내기 때문에 Producer는 인증 서버, Consumer는 회원 API 서버가 된다.

// 인증 서버 
package com.dev.nbbang.auth.global.config;

import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;

import java.util.HashMap;
import java.util.Map;

@EnableKafka   
@Configuration
public class KafkaProducerConfig {
    private final String host;
    private final String port;

    // 카프라 Bootstrap Server Config 프로퍼티 파일에서 가져오기
    public KafkaProducerConfig(@Value("${kafka.host}") String host, @Value("${kafka.port}") String port) {
        this.host = host;
        this.port = port;
    }

    @Bean
    public ProducerFactory<String, String> producerFactory() {
        // 프로퍼티 설정
        Map<String, Object> properties = new HashMap<>();

        // Bootstrap Server는 일반적으로 9092번 포트를 사용한다.
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, host + ":" + port);

        // Key, Value Serialize 프로퍼티 설정
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);

        return new DefaultKafkaProducerFactory<>(properties);
    }
		
		// KafakaTemplate을 이용해 데이터 실제 전송, 설정한 프로퍼티를 이용
    @Bean
    public KafkaTemplate<String, String> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }
}

Consumer Configuration

메세지를 전달 받는 회원 API 서버도 동일하게 Java Configuration 설정을 해준다.

package com.dev.nbbang.member.global.config;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;

import java.util.HashMap;
import java.util.Map;

@EnableKafka
@Configuration
public class KafkaConsumerConfig {
    private final String host;
    private final String port;

    public KafkaConsumerConfig(@Value("${kafka.host}") String host, @Value("${kafka.port}") String port) {
        this.host = host;
        this.port = port;
    }

    @Bean
    public ConsumerFactory<String, String> consumerFactory() {
        Map<String, Object> properties = new HashMap<>();

        //Bootstrap Server 설정
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, host + ":" + port);

        // Key, Value Deserialize 프로퍼티 설정
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);

        // 그룹 아이디 지정
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "consumer-group-id");
        return new DefaultKafkaConsumerFactory<>(properties);
    }

		
		// @KafkaListener가 로드하는 컨테이너
    @Bean
    public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory
                = new ConcurrentKafkaListenerContainerFactory<>();

        kafkaListenerContainerFactory.setConsumerFactory(consumerFactory());

        return kafkaListenerContainerFactory;
    }
}
반응형
저작자표시 비영리 변경금지 (새창열림)

'Backend > Kafka' 카테고리의 다른 글

Kafka를 이용해 Producer/Consumer 맛보기! - Producer/Consumer  (0) 2022.05.06
    'Backend/Kafka' 카테고리의 다른 글
    • Kafka를 이용해 Producer/Consumer 맛보기! - Producer/Consumer
    Zayson
    Zayson
    공부한 내용을 정리하는 공간

    티스토리툴바