Festina lente

헷갈리는 WebClient Timeout

SpringBoot 환경에서 HTTP 요청을 보낼 때 주로 사용하는 client 는 RestTemplate 과 WebClient 가 있다. RestTemplate 은 Spring 3.0 부터 포함된 client 로, mvc 환경에서 blocking I/O 방식으로 요청을 보낼 때 주로 사용되어왔고, WebClient 는 (비교적 ?) 최신인 5.0 부터 도입되어, webflux 환경에서 non-blocking I/O 로 요청을 보낼 때 애용되어왔다. WebClient 의 connection manager 는 기본 구현체로 reactor-netty 를, 그리고 reactor-netty 는 netty 의 wrapper 로, 실상 HTTP 요청을 보내는 connection 을 관리하는 주체는 netty framework 를 사용한다....

March 4, 2025 · 10 min · cjlee38

reactor-kafka 는 조심하자

지난 약 1년 조금 넘는 기간 동안, 미들웨어 기능을 담당하는 알림 플랫폼을 구축하는 업무를 진행했다. 알림 플랫폼 구축 시 요구사항 중 하나는 알림 발송을 수신하는 서버 역할의 서비스에는 TPS 에 대한 제한이 있지만, 알림 발송을 요청하는 클라이언트의 서비스는 TPS 에 대한 제어 없이 무작위로 발송할 수 있어야 한다는 것이기 때문에, 적절한 제어와 high throughput 을 보장하기 위해 spring webflux 와 kafka 를 사용했다. spring webflux 환경에서, kafka 를 사용할 일이 생기면 일반적으로 reactor-kafka 를 채택하기 마련이다....

January 21, 2025 · 7 min · cjlee38

Git absorb 소개

어디서 처음 봤는지는 정확히 기억 안나지만, 우연히 괜찮은 git 관련 오픈소스를 발견해서 소개해본다. 이름은 git absorb 라고, git 기반의 일종의 extension 인데, commit history를 관리할 때 유용하게 사용할 수 있다. 먼저 어떤 extension 인지 서두에 정리해보자면, 내가 코드를 수정한 뒤, 해당 작업을 과거의 commit 어딘가에 같이 포함시키고 싶을 때, “가장 관련성이 높은 commit을 찾아”서 흡수시킬 수 있다. fixup commit 먼저 git absorb 를 알기 전에 먼저 알아둬야 하는 것이 있는데, 바로 fixup commit이다....

June 5, 2024 · 3 min · cjlee38

객체지향은 정신병이다.

정말 오랜만에 블로그 글을 쓰는데 첫 타이틀부터 정신병이라는 과격한 단어를 넣은 스스로가 새삼 우습기도 하다. 이 글을 읽는 사람들이 각기 다른 이유로 제목을 보고 이 글을 클릭했겠지만, 어쨌든 눈길을 끌고 이 글을 클릭하도록 유도했다는 점으로 족하다. 객체 지향과 클린 코드 최근 한 선배 개발자분과 코드에 대한 이야기를 하다가 “객체지향은 정신병이다” 라는 꽤나 과격한 표현을 들었다. 우아한테크코스 를 진행하면서 정말 ‘객체’ 를 ‘지향’했던 과거의 내가 들으면 상당히 당황스러운 말이었겠지만, 실무를 배우고 있는 현재의 나로서는 차마 대놓고 부정할 수는 없는 발언이었다....

November 29, 2023 · 8 min · cjlee38

Java Memory Model explained (feat. Effective Java, Item 78)

개요 이펙티브 자바의 ‘아이템 78 공유 중인 가변 데이터는 동기화해 사용하라’ 에서는 멀티태스킹 환경에서 발생할 수 있는 동시성 문제들을 소개하고, 이에 대한 해결책을 제시한다. 아이템 78을 읽어본 사람이라면, 아래의 유명한 코드를 한 번쯤은 본 적이 있을 것이다. public class StopThread { private static boolean stopRequested; public static void main(String[] args) throws InterruptedException { Thread backgroundThread = new Thread(() -> { int i = 0; while (!stopRequested) i++; }); backgroundThread.start(); TimeUnit.SECONDS.sleep(1); stopRequested = true; } } 위 코드를 읽어보면, stopRequested 가 1초 뒤에 true 로 바뀌었으므로 백그라운드 스레드는 종료되어야 할 것 같지만, 실제로 무한 루프를 돌게 된다....

March 5, 2023 · 10 min · cjlee38

도메인과 레이어드 아키텍처

약 8개월 간의 우아한테크코스를 진행하면서 배우고, 또 고민한 것 중 하나는, 소프트웨어의 책임을 어떻게 분리할 것인가에 관한 것이었다. 레벨 1 당시에는 콘솔 프로그래밍으로 도메인을 어떻게 구성할 것인지에 대해 다루었다. 레벨 2 로 넘어와서는 Spark Java 와 Spring을 추가하면서 도메인을 안정적으로 만드는 것이 왜 중요한지에 대해 학습하였고, 레벨 3에 이르러서는 JPA를 사용하면서 데이터베이스를 연결했을 때 겪는 문제점들을 ORM이 어떻게 풀어나가는지 배웠다. 정리하자면, 어떻게 하면 도메인을 잘 만들 수 있는지, 그리고 이 도메인을 외부 환경으로부터 어떻게 격리하여 흔들리지 않게 만들 수 있는지를 학습하는 과정이었다....

October 25, 2022 · 7 min · cjlee38

문자 인코딩과 MySQL varchar

1. 문자 인코딩이란 문자 인코딩이란 사용자가 입력한 문자나 기호들을 컴퓨터가 이용할 수 있는 신호로 만드는 것을 말한다. 1 우리가 작성한 모든 텍스트는 결국 CPU 상에서 2진수로 처리된다. 사람이 작성한 글을 2진수로 변환하고, 2진수를 다시 사람이 읽을 수 있도록 만드는 작업을 각각 인코딩(encoding)과 디코딩(decoding)이라고 표현한다. 이러한 인코딩을 하기 위해서는 서로 약속한 ‘문자열 세트’가 필요하다. 가장 대표적인 문자열 세트는 ASCII다. ASCII는 1963년 미국 ANSI에서 표준화한 7 bit 부호 체계로 128 개의 기호(33개의 제어문자와 95개의 출력문자)를 표현할 수 있다....

October 2, 2022 · 4 min · cjlee38

스프링에서 환경을 분리하는 방법

프로젝트를 local에서만 개발하는게 아니라면, 그리고 develop 이나 staging, production 을 구분해서 개발하게 된다면 필연적으로 서로 다른 설정값이 필요하게 된다. local 에서는 테스트 용도이므로 H2 의 in-memory DB 를 사용할 수 있지만, production 환경에서는 반드시 안정적인 밴더사의 RDBMS와 인스턴스를 사용하게 된다. 가령, local에서 개발을 마치고, 이제 production 에서 코드를 가져와 실행하려면 당연히 datasource 를 바꿔주어야 한다. # as-is (local) spring: datasource: url: jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE username: sa # to-be (production, or develop ...) spring: datasource: url: jdbc:h2:192....

August 13, 2022 · 4 min · cjlee38

kotlin property

코틀린을 처음 접하면, 익숙한 field 라는 용어 대신 property 라는 용어를 접하게 된다. property 라는 용어는 지난 파이썬 Property까지 가는 길 에서 한번 다뤘던 개념과 사실상 같다고 보아도 무방하다. property는 단순하게 이야기하면 클래스 내에 담겨있는 field, getter , setter 를 통칭하여 의미하다. Java 에서는 이를 private 으로 필드를 숨기고, getter 와 setter 를 제공함으로서 property를 흉내낸다. public class SomeObject { private int someInteger; private String someString; public int getSomeInteger() { return this....

June 9, 2022 · 4 min · cjlee38

python property

흔히 “객체지향” 에서는, 객체가 갖고 있는 Field 를 적절하게 외부로 노출시키거나 숨기기 위해, getter/setter를 사용한다. Java 에서는 private 이라는 키워드로 갖고 있는 멤버변수들을 모두 숨기고, 보여줄 내용은 getter 메소드를, 외부에 의해 변경되어도 되는 변수는 setter 메소드를 활용해 데이터를 관리한다. 따라서 직접적으로 변수에 접근하는 것은 원천적으로 금지되어 있고, 메소드 호출을 통해서만 데이터를 조작할 수 있다. class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this....

September 16, 2021 · 12 min · cjlee38