Java & Kotlin

인터페이스의 메서드가 각기 다른 리턴 타입과 파라미터를 필요로 한다면?

1. 문제 인터페이스를 정의하여 구체 클래스의 세부 구현을 숨기는 것은 객체 지향에서 중요한 캡슐화의 한 방법입니다. 그런데 구체 클래스가 인터페이스를 구현하는 시점에는 인터페이스의 모든 메서드(Private, Default, Static 제외)를 반드시 오버라이딩해야 합니다. 그런데 회사에서 코드를 짜다보니 하다보니 아래와 같은 상황을 마주했습니다. public interface Reward { void giveReward(); } public class CashReward implements Reward{ } public class CouponReward implements Reward { } Reward는 '보상'과 관련된 인터페이스이며 보상을 지급하는 giveReward() 메서드가 있습니다. 세..

2023.05.08 게시됨

Gradle

Gradle 기반 멀티 모듈 프로젝트를 관리하는 방법

0. Gradle 멀티 모듈 프로젝트 이번 글에서는 Gradle 기반 멀티 모듈 프로젝트 관리에 대해 소개하려고 합니다. 많은 회사들에서는 아래와 같은 구조의 멀티 모듈 프로젝트를 사용합니다. 멀티 모듈로 프로젝트를 구성하지 않으면 여러 가지 기능이 한 데 묶인 거대한 프로젝트 하나를 관리하는 데 너무 많은 리소스가 들어가기 때문입니다. - root - core - ... - api - ... - async - ... - batch - ... - admin - ... ... 특히 core 모듈 안에는 api, async, batch, admin 등에서 끌어다쓰는 공용 클래스가 다수 존재하도록 설계되는 경우가 많습니다. 한편, Gradle은 이런 상황에서 개별 모듈에 대한 의존성을 관리하는 동시에 모듈 ..

2023.04.29 게시됨

Spring & Springboot

단위 테스트에서 @InjectMocks, @Mock VS @MockBean 이해하기

1. @SpringBootTest와 @MockBean @SpringBootTest는 Junit 테스트에서 @SpringBootApplication 어노테이션을 찾아 하위의 모든 Bean들을 스캔하여 Spring ApplicationContext를 로딩하는 데 사용됩니다. 그리고 이렇게 로딩된 컨텍스트 아래에서 @Autowired로 간단하게 테스트의 대상이 되는 객체를 주입할 수 있게 됩니다. 한편, @MockBean 역시 SpringBoot에서 제공하는 어노테이션으로, Spring ApplicationContext에서 관리되는 Bean을 대체하기 위해 Mockito와 함께 사용됩니다. 즉, @SpringBootTest를 통해 로드한 빈을 Mock 객체로 주입할 수 있게 만드는 것이죠. 그러면 지금까지 설..

2023.04.15 게시됨

Java & Kotlin

[Java] Thread 안에서 발생하는 예외는 어떻게 처리되나

0. 문제 이번 글에서는 자바 개별 Thread에서 발생하는 예외를 어떻게 처리할 것인가에 대한 내용을 정리해보려고 합니다. 먼저 간단한 문제 상황을 보기 위해 아래 테스트 코드를 작성했습니다. @Test void threadExceptionTest() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); int successCount = 0; for (int i = 0; i { throw new NullPointerException(); }); succ..

2023.03.31 게시됨

Spring & Springboot

JPA 연관관계 편의 메서드의 위치에 대한 내 생각

1. 문제 JPA에서 연관관계 편의 메서드는 양방향 연관관계를 한 번에 설정하기 위해 작성하는 메서드 입니다. 이 때, 통상적으로 엔티티 A(Many), B(One)가 서로 양방향 관계일 때 연관관계 편의 메서드는 총 3가지 케이스로 작성할 수 있습니다. [1] A에 작성하고, B까지 관리한다. [2] B에 작성하고, A까지 관리한다. [3] A, B 각각에 대해 작성한다. 그런데 여기서 [3]번 방식은 둘 중의 한 곳에서라도 메서드 호출을 빼먹으면 논리적인 문제가 생기고 코드의 관리 측면도 복잡해져서 지양하는 패턴입니다. 그러면 [1], [2] 케이스 중에 어디에 연관관계 편의 메서드를 정의하는 게 좋을까요? 이번 글에서는 이 질문에 대한 제 생각을 기록해보려고 합니다. 2. 단순한 ManyToOne ..

2023.03.15 게시됨

Data Engineering

자주 사용하는 Kafka CLI 정리하기

이번 글에서는 꽤 자주 사용하는데 매 번 찾아봤던 카프카 CLI를 정리해보겠습니다. 모든 명령어는 kafka > bin 경로 안에서 수행되고, SASL 등 인증이 필요한 경우 --command-config 을 명령어에 붙여서 수행합니다. 1. Topic 관련 - Topic 목록 확인 $ ./kafka-topics.sh --bootstrap-server {server-address} --list - 개별 Topic 정보 확인 $ ./kafka-topics.sh --describe --bootstrap-server {server-address} --topic {topic-name} - Topic 생성 $ ./kafka-topics.sh --bootstrap-server {server-address} --re..

2023.02.24 게시됨

Spring & Springboot

[Spring] @CacheEvict 없이 @Cacheable을 쓸 때 생길 수 있는 문제

1. 문제 캐시의 종류에는 크게 두 가지가 있는데요. 바로 로컬 캐시와 글로벌 캐시입니다. 로컬 캐시는 각 서버마다 존재하는 캐시이고, 글로벌 캐시는 여러 서버가 공유할 수 있는 캐시입니다. 부하 분산을 위해 여러 서버를 가지고 서비스를 운영하고 있다면 아마 글로벌 캐시 전략을 가져가고 있을 것입니다. 이번 글에서는 Springboot + JPA + Redis를 활용해서 기본적인 캐시 사용 전략을 실습해보고, 반드시 주의해야 할 내용 한 가지를 짚어보려고 합니다. 2. 테스트 환경 구축 먼저 캐시를 사용할 때 기본적으로 알아야 할 개념인 @Cacheable과 @CacheEvict가 무엇인지 알아보기 위해 간단한 테스트 환경을 구축해보겠습니다. Redis를 설치하지 않으셨다면 여기에서 설치하실 수 있습니다..

2023.02.22 게시됨

Spring & Springboot

@DataJpaTest의 동작 방식과 몇 가지 주의사항

1. @DataJpaTest @DataJpaTest는 이름에서 알 수 있듯이 JPA Component의 테스트에 집중하기 위한 어노테이션입니다. 위 사진의 빨간색 박스로 표시한 내용을 자세히 읽어보면 크게 세 가지 특징이 있습니다. 첫째, @DataJpaTest는 Transactional하며 각 테스트의 마지막에 롤백을 합니다. 둘째, 기본적으로 in-memory DB를 사용하며, @AutoConfigureTestDatabase 어노테이션을 통해 사용자가 지정하는 DB로 설정할 수 있습니다. 셋째, Bean 스캔의 범위가 한정적입니다. 어플리케이션에서 등록한 모든 Bean을 대상으로 테스트를 하기 위해서는 @SpringBootTest를 사용해야 합니다. 각 내용에 대해 자세히 설명해보겠습니다. 2. Ro..

2023.02.12 게시됨

Data Engineering

Kafka offset reset을 통한 이벤트 Consuming

0. Kafka Offset 카프카의 가장 큰 구성 요소는 프로듀서(Producer)와 컨슈머(Consumer)입니다. 프로듀서가 토픽에 메시지를 송신하면 토픽은 파티션들에 메시지를 복제하고, 컨슈머는 각 파티션에서 아직 처리하지 않은 메시지를 가져와 소비(Consume)합니다. 이 때, 컨슈머는 자신이 처리한 메시지와 아직 처리하지 않은 메시지를 구분하기 위해 Offset 정보를 사용하는데요. 위 그림에서 하나의 토픽에는 여러 개의 파티션이 존재하며, 컨슈머는 각 파티션에 대해 자신이 처리한 메시지의 위치를 Offset으로 기록합니다. 즉, 파티션 1~5의 Offset은 5, 4, 3, 2, 4가 되겠죠. 그런데 만약 아래와 같은 상황처럼 컨슈머가 자신이 이미 처리한 메시지를 다시 처리해야 하는 상황이..

2023.02.01 게시됨

DevOps

Groovy를 이용해서 Jenkins 설정 자동화하기(사용자 생성, 고정 API Token 입력)

0. Docker 환경에서 Jenkins 서버 띄우기 이전 글[Jenkins, Docker를 통한 CI 환경 구축과 Slack 알람 받기]에서 도커 환경에서 Jenkins 서버를 띄우는 방법에 대해 설명했습니다. 그런데 이 글에서는 DockerHub에서 제공하는 Jenkins lts 버전 이미지를 Pull 받아 사용했었는데요. 사실 위 글에서 사용한 이미지에는 어떤 커스텀화 된 설정들이 없기 때문에 최초 서버 접속 시 아래와 같이 사용자의 비밀번호를 입력하고 플러그인 설치를 묻는 과정, 그 후에 계정을 설정하는 등의 과정을 수작업으로 진행해야 했습니다. 1. Groovy 파일을 이용해서 사용자 자동 생성 Jenkins Docker의 공식 깃허브를 보면, 기본 Jenkins 이미지에 사용자가 원하는 기능을..

2023.01.18 게시됨