목록전체 글 (105)
Kuma's Curious Paradise
김현우의 을 읽는 동안 여러 번 고개를 끄덕였다. 문장 하나하나가 마치 오래된 교훈처럼 들렸다. 함부로 공감한다고 하지 말라. 이해한다고 쉽게 말하지 말라. 맞다. 인간은 타인을 너무 쉽게 재단한다. 나 역시 얼마나 자주 "네 마음 알아"라고 말했던가. 그럴 때마다 나는 잠시나마 온화한 얼굴을 하고 상대의 세계를 이해했다고 착각했을지 모르겠다. 그러나 책을 덮고 나서 남은 것은 묘한 답답함이었다. 그렇다면 우리는 무엇을 할 수 있는가. 윤리의 문턱이 높아질수록 타인에게 다가가는 길은 멀어진다. 마치 담장 높은 집 앞에 선 것처럼. 초인종을 누르기가 망설여지고 나는 받아들여지지 못할 것 같다. 담장은 분명 필요하다. 누군가 내 집을 함부로 드나들지 못하게 막아준다. 하지만 동시에 그 벽은 내게 오는 길을..
지난번 글에서 circuit breaker의 구조에 대해서 살펴보았다. 이번 글에서는 WebClient에서 CircuitBreaker를 적용하는 방법과 Reactive(Flux/Mono) 환경에서 서킷 브레이커가 내부적으로 어떻게 동작하는지를 다뤄보려고 한다. 좀 두서없는 글이 될 수도 있을 것 같다. 1. webclient 사용 시 circuit breaker 적용하는 법WebClient로 외부 API를 호출할 때 서킷 브레이커를 적용하는 방법은 의외로 간단하다.아래와 같이 .transformDeferred() 안에 CircuitBreakerOperator를 추가해주면 끝이다.private final CustomCircuitBreaker customCircuitBreaker;public Mono get..
메인 페이지를 개발하다 보면, 여러 서버를 찔러서 한꺼번에 데이터를 가져와 합쳐야 하는 경우가 있다. 이들은 속도가 중요하기 때문에 Reactor 형식으로 구성되어 있다. 예를 들어, 메인 페이지에 필요한 메뉴가 4가지라면 다음과 같은 비동기 호출이 있을 수 있다. Mono fetchFirstMenu();Mono fetchSecondMenu();Mono fetchThirdMenu();Mono fetchFourthMenu();이때 결과를 합쳐서 TotalMenuResponseDto에 담아야 한다면 어떻게 해야 할까? 고민이 된다면 tupel과 zip(), flatMap() 등의 개념을 이해해야 할 때다. 1. Tuple이란 무엇인가?Tuple(튜플)은 수학에서 “순서가 있는 값들의 모음”이라는 뜻이다. T..
데이터베이스 테이블을 보다 보면 utf8mb4_unicode_ci, utf8mb4_general_ci 같은 낯선 문구를 종종 마주하게 된다. 이는 바로 collation을 의미하는데, 오늘은 collation이 무엇인지, 어떻게 사용되는지 등을 살펴보자. 1. Collation이란?Collation은 데이터베이스에서 문자열을 비교하고 정렬하는 규칙을 말한다.예를 들어, Apple과 apple을 같은 것으로 볼지, 다른 것으로 볼지는 collation에 따라 달라진다. 한글이나 특수문자 정렬은 어떻게 할지 같은 규칙 등도 모두 collation과 관계가 있다. Character Set(문자 집합): 어떤 문자를 저장할 수 있는가?예: UTF-8, ASCII, EUC-KRCollation(콜레이션): 저장..
좋아서 두 번 읽은 책이다. 아마 세 번을 읽어도 지루하지 않을 것 같다.작법에 대한 수많은 책들 중 단연코 눈에 띄는 책이다. 그러나 이 책을 덮을 때, 글쓰기보다는 삶을 더 오래 생각하게 된다. 좋은 에세이가 무엇인가를 묻는 동시에, 좋은 삶이 무엇인지를 묻기 때문이다. "논픽션의 페르소나는 대리인이 아니다. 논픽션 작가는 소설가나 시인이라면 거리를 둘 수 있는 변명과 낭패감을 공개적으로 드러내야 한다. 공공장소에서 소파에 드러눕는 거나 매한가지다." 소설가는 허구의 인물을 내세워 그의 그림자속에 숨을 수 있다. 시인은 목소리의 굴절 속에서 스스로를 가릴 수 있다. 그러나 논픽션 작가는 달아날 수 없다. 그는 자기 얼굴을 드러내야 한다. 낭패와 변명, 불편한 욕망과 자기 소외까지도. 그것은 마치 공..
1. 들어가며외부 API를 호출하며 장애 전파를 막기 위해 CircuitBreaker를 사용할 일이 생겼다. 적용 자체는 매우 쉽다.스프링 부트에서 제공하는 어노테이션 덕분이다. 예를 들면 서킷 브레이커를 적용하는 코드는 이렇게 생겼다. @CircuitBreaker(name = "externalApi", fallbackMethod = "fallback")public String getResult() { return restTemplate.getForObject("https://externalapi.com/data", String.class);}이렇게 어노테이션을 붙이면... 외부 API 실패율이 일정 수준 이상이면 호출 자체를 차단하고일정 시간이 지나면 일부 요청만 다시 시도해보고여전히 실패하면 ..
[문제 상황]- 사용자가 '현황_2025_07_27' 파일을 요청할 경우, S3에 이미 올라가 있는 파일을 지우고 새 파일을 다시 업로드한 뒤 파일 주소를 내려주는 로직을 작성함. - 그러나 새 파일이 아닌 이전 파일이 다운로드되는 문제가 생김. [결론]- cloudfront에 이전 파일이 캐시되어 있었음. - '현황_2025_07_27'이라는 파일명이 같으므로, cloudfront는 파일이 삭제된 것을 모르고 똑같이 이전 파일을 내려줌. - 해당 버킷 디렉토리의 cloudfront의 캐시를 0으로 만들어 캐시를 무효화 하도록 함. [대안]- 코드 레벨에서는 Cache-Control: no-store나 max-age=0 등의 헤더를 S3 업로드 시 설정할 수도 있음. - 또 다른 대안으로는 cloud..
Spring 기반 애플리케이션에서 외부 API를 호출하는 방식은 다양하다.최근에는 WebClient를 사용하는 경우가 많아졌지만, 여전히 @Async, CompletableFuture를 활용한 방식도 자주 보여진다.이러한 방식들은 겉보기에는 비슷해 보이지만, 내부 동작 원리와 스레드 처리 방식이 다르다.이들은 정확히 어떻게 다른걸까? 이 글에서는 아래와 같은 질문에 답하기 위해, 각 방식이 어떻게 동작하는지, 특히 WebClient는 어느 때 적합하며 어떻게 다루어야 하는지를 설명한다. WebClient는 논블로킹이라는데, 그게 정확히 어떤 의미일까?@Async와 CompletableFuture는 어떤 차이가 있을까?외부 API 요청이 많아지면 어떤 방식이 더 유리할까? 1. 동기/비동기, 블로킹/논블로..
요즘 들어 무엇을 읽었는지 가물가물한 경우가 많아졌다. 좋은 책을 설명할 때 내용이 떠오르지 않아 혀가 머릿속을 맴도는 일도 많아졌다. 오랜만에 책 후기를 써 본다. "수업 종이 울리고 고개를 들어보니, 나를 포함한 예순 명의 아이들이 전부 시커먼 형상을 앞에 두고 앉아 있었다. 저마다의 좌절감을 담은 그림 예순 장. 흰 석고상을 그린 검은 그림은 번역 불가능성의 증거다. 이게 이렇게 생겼는데, 눈에 뚜렷이 보이는데, 왜 종이에 그대로 그려지지 않나. 이게 이런 뜻인데, 너무나 빤한데, 왜 글로 옮겨지지 않나." 뚜렷하게 보이는데도 그대로 옮겨지지 않는 대상, 그리고 그 실패 앞에 선 사람의 당혹감을 표현한 문장이다. 이 장면 하나로 저자는 이 책의 설명을 끝냈다고 해도 과언이 아니다. 훌륭한 책이다...
1. 배경스프링부트 실행 시 다음과 같은 WARN 로그 발생.2025-06-25T11:05:17.775+09:00 WARN 39055 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'shedlockConfig' of type [com.aptner.utility.config.ShedlockConfig$$SpringCGLIB$$0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently cr..