Gradle

Gradle의 의존성 충돌(Dependency Conflict) 관리 전략

0. 문제 애플리케이션의 규모가 커질수록 많은 의존성을 정의하게 되고, 의존성들이 많아질수록 보이지 않는 의존성의 충돌이 잦아지기 마련입니다. 예를 들어, 아래 두 개의 의존성을 살펴보겠습니다. implementation("com.google.guava:guava:20.0") // [1] implementation("org.apache.hadoop:hadoop-common:2.7.4") // [2] [1] guava는 구글에서 제공하는 Java 라이브러리 집합으로, 컬렉션이나 해시, 문자열 처리 등을 위한 다양한 기능을 제공합니다. 여기서는 버전 20.0으로 선언했습니다. [2] 다음으로 hadoop-common 2.7.4 버전 의존성을 정의했습니다. hadoop-common 라이브러리는 Hadoop 공..

2023.07.06 게시됨

Data Engineering

Kafka Producer Message Batching과 몇 가지 성능 튜닝 옵션들

이번 시간에는 카프카 프로듀서의 기본적인 구조와 레코드의 배치(Batch) 전송에 대해 소개합니다. 그리고 레코드의 배치 전송을 통해 얻을 수 있는 이득과 고려해야 할 점, 그리고 이와 관련된 성능 튜닝을 할 수 있는 몇 가지 옵션에 대해 이야기해보겠습니다. 1. Kafka Producer, Record Accumulator 먼저 카프카 프로듀서가 메시지를 전송하는 방식에 대해 간략히 짚어보겠습니다. 기본적으로 카프카 프로듀서는 아래 그림과 같은 구조를 바탕으로 메시지를 전송합니다. 크게 Producer → Serializer → Partitioner → RecordAccumulator → Sender Thread → Broker 의 흐름을 따르는데요. 조금 더 구체적인 이해를 위해 메시지 전송 순서에 ..

2023.07.01 게시됨

DevOps

이미 바인딩 되어있는 DNS VIP를 교체할 때 테스트하는 방법

0. 문제 이번 글에서는 DNS VIP를 교체하는 시나리오에서 신규 VIP를 테스트하는 방법에 대해 소개하려고 합니다. DNS VIP(Virtual IP)는 DNS에서 사용되는 가상 IP 주소를 의미합니다. 이러한 VIP는 DNS에 바인딩되어 실질적인 '단일 창구 역할'을 하며 로드 밸런서같은 역할을 할 수 있는데요. 아래와 같이 특정 도메인에 대한 트래픽이 여러 서버로 리디렉션되는 상황을 고려할 때, VIP는 중요한 개념이 됩니다. 그런데 만약 신규 서버를 발급받고, 신규 서버들을 바인딩하는 새로운 VIP를 기존 DNS에 연결하려면 어떻게 해야할까요? 물론 이 상황에서 중요한 가정은 기존 서버들에 들어오던 요청을 그대로 받으면서 테스트를 진행해야 한다는 것입니다. 다시 말해, DNS에 신규 VIP를 무..

2023.06.25 게시됨

Thinking

아는만큼 보인다는 말

지금 회사에 오기 전까지, 대학생 때는 매 분기 혹은 반기마다의 목표를 세워 벽에 붙여뒀다. 가령, 코딩 테스트 몇 문제를 푼다거나 JPA에 대한 어느정도 수준까지를 공부한다거나 하는 식의 목표였다. 이런 목표들을 세우고 차근차근 달성해나가는 것이 현재를 살 때 불안감을 없애는 방식이자, 미래에 원하는 결과가 나오지 않았을 때에도 내가 열심히 했던 것과 그렇지 못했던 것에 대한 확인 지표였다고 생각한다. 지금도 이런 생각은 유효해서, 회사에서 매 달 업무 선별 회의를 할 때도 약간은 머리아플 것 같은 문제들을 해보겠다는 용기를 내기도 한다. 이 과정에서 모르는 내용들을 배울 수 있고 어떤 부분을 공부해 나가야할 지에 대한 가이드가 되기 때문이다. 그 외에도 카프카를 공부한다거나 쿼리에 대해 좀 더 공부해..

2023.06.24 게시됨

Data Engineering

Kafka Consumer, ConsumerGroup 그리고 Rebalancing

이번 글에서는 Kafka에서 중요한 개념 중에 하나인 Consumer Rebalancing에 대해 실습하는 시간을 가져보려고 합니다. 테스트 환경은 AWS Ubuntu EC2에 Kafka Confluent를 설치하고 진행합니다. 실습 환경은 OS나 Kafka / Kafka Confluent에 크게 영향을 받지는 않으니, 카프카가 설치된 각자의 개발 환경에서 실습할 수 있습니다. # 테스트 환경 정보 ubuntu@sunghyeon:~$ hostnamectl Static hostname: sunghyeon Icon name: computer-vm Chassis: vm Machine ID: 3cf5524f3ebb4baba881e9800cd651bc Boot ID: db655d7ad94b4524ae71f3283..

2023.06.11 게시됨

Java & Kotlin

내가 이해한 Garbage Collection

자바 개발자라면 Garbage Collection(이하 GC)에 대해 당연히 들어보고 한 번쯤은 공부해봤으리라 생각합니다. 하지만 어느 수준 이상의 메모리를 사용하는 애플리케이션 환경이 아니고서는 GC에 직접적인 관심을 가지기는 어려운 것 같은데요. 저 역시 얼마 전 회사에서 운영하고 있는 PM 서버를 VM으로 이사하면서 JVM 메모리 할당과 GC 옵션에 대해 들여다볼 기회가 있었고, 이번 기회에 GC의 동작 방식과 여러 가지 GC 방법에 대해 나름대로의 이해를 정리해보려고 합니다. 1. GC, Stop the word! GC는 JVM에서 제공하는 메모리 관리 메커니즘입니다. Heap 영역에서 더 이상 참조되지 않는 객체를 메모리에서 제거하여 앞으로 애플리케이션 동작에 있어 필요한 메모리를 확보하는 데 ..

2023.06.05 게시됨

MySQL

M1 Mac 환경에서 MySQL 사용 환경 구축하기

이번 글에서는 M1 Mac 환경에서 MySQL을 설치하고 서버를 실행하는 방법을 정리해보려고 합니다. 1. Homebrew로 MySQL 설치 Homebrew는 macOS 전용 패키지 관리자로, 커맨드라인 도구나 시스템 패키지들을 설치하는 데 편의를 제공합니다. M1 환경에서 개발하시는 분이라면 Homebrew가 설치되어 있겠지만, 혹시 깔려있지 않으신 분은 아래 명령어로 설치하실 수 있습니다. /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 설치가 완료되면 아래와 같이 /opt/homebrew 경로에 관련 파일들이 생성된 것을 볼 수 있습니다. Homebrew는 전용 디렉토리에 패..

2023.06.03 게시됨

Gradle

Maven 기반 멀티 모듈 프로젝트, Gradle로 전환하기

최근 꽤 큰 리소스를 들여 팀의 빌드 툴을 Maven에서 Gradle로 전환하는 작업을 했습니다. Maven을 기반으로 운영하고 있던 멀티 모듈 프로젝트는 빌드 시간도 오래 걸렸고, XML 방식의 의존성 설정이나 플러그인 등은 프로젝트를 운영하는 데 복잡성을 증대시킨다고 생각했기 때문인데요. 이번 글에서는 빌드 툴을 Gradle로 전환했던 전반적인 과정과 Gradle을 더 제대로 사용하기 위해 알아야 할 몇 가지 내용을 소개하려고 합니다. 1. Why gradle? 왜 Maven에서 Gradle로 빌드 툴을 전환해야 하는가? 에 대한 답은 "가독성 + 빠른 빌드 + 다양한 기능 제공"에 있다고 생각합니다. 실제로 저희 프로젝트 중 하나의 프로젝트를 Gradle로 전환했을 때 결과입니다. ... [INFO..

2023.05.21 게시됨

Gradle

Gradle에서src/main/java에 위치한 XML 파일 빌드하기

0. 문제 Mybatis를 사용하면 Mapper 인터페이스와 Mapper.xml 파일을 생성해야 합니다. 그리고 일반적으로 Mapper.xml 파일은 XML 설정 파일 분류이기 때문에 resources 하위에 위치시키는데요. 하지만 그렇게 되면 아래 사진과 같이 메서드를 정의한 Mapper 인터페이스의 패키지와 실제 쿼리가 정의된 XML 파일의 패키지가 멀리 떨어져(?) 있게 되어 도메인 개발에서 불편함을 겪게 됩니다. 이러한 불편함을 해소하기 위해 저희 팀에서는 src > main > ... > repository 하위에 Mybatis 인터페이스와 XML 파일을 같이 정의해두고 있습니다. 그런데, 여기서도 문제가 하나 있습니다. Gradle CompileJava 작업에서 기본적으로 'src > main..

2023.05.13 게시됨

Java & Kotlin

Thread 클래스를 상속하는 것보다 Runnable 인터페이스를 구현해야 하는 이유

이번 글에서는 자바에서 쓰레드를 구현하는 가장 핵심적인 두 가지 Thread 클래스와 Runnable 인터페이스에 대해 간략하게 소개하려고 합니다. 먼저 쓰레드의 생명 주기를 간략하게 보고, 왜 Runnable 인터페이스를 Implements 하는 방식의 구현이 Thread 클래스를 상속해서 구현하는 방식보다 나은지 그 이유를 적어보겠습니다. 1. 쓰레드의 생명 주기 쓰레드는 크게 아래와 같이 5가지 상태의 생명 주기를 갖습니다. New 쓰레드가 만들어진 상태로 아직 start() 메소드가 호출되지 않은 상태입니다. Runnable (실행대기) 쓰레드가 실행되기 위한 준비 단계입니다. 코드 상에서 start() 메소드를 호출하면 run() 메소드에 설정된 쓰레드가 Runnable 상태로 진입합니다. Ru..

2023.05.09 게시됨