환경 및 전제 조건

  • Pub/Sub
  • RDB
  • Java


배경

  • 리스트 데이터를 병렬로 처리하여 Pub/Sub 이벤트를 발행하던 중, Database의 최종 상태값이 의도와 다르게 저장되는 현상이 발생함.
  • 모든 DB 쓰기 작업 로그가 정상임에도 불구하고 데이터 정합성이 깨지는 현상이 발생.


이슈

  • parallelStream()을 이용해 대량의 메시지를 전송한 뒤 해당 항목들의 상태를 일괄 업데이트하는 로직에서 문제 발생.
  • GCP Pub/Sub으로부터 “처리 성공(SUCCESS)” 응답을 받아 DB 업데이트까지 마쳤으나 최종 결과는 “전송 완료(PUBLISHED)” 상태로 남아있음.
  • 해당 코드는 아니지만 대략적으로 아래와 같은 형식의 코드.
// 1. 병렬 이벤트 발행 (Main Thread)
jobList.parallelStream().forEach(job -> {
    // Pub/Sub 메시지 전송
    publishEvent(job); 
});

// ---------------------------------------------------------
// [핵심 지점] 이 사이에 Pub/Sub 구독에서 SUCCESS 응답이 먼저 도착!
// 별도의 구독 스레드(Sub Thread)가 DB를 이미 SUCCESS로 업데이트함
// ---------------------------------------------------------

// 2. 발행 완료 후 상태 업데이트 (Main Thread)
// 뒤늦게 실행되어 DB를 "PUBLISHED"로 덮어버림
jobRepository.findAllById(ids).forEach(job -> {
    // AS-IS: 조건문 없이 무조건 덮어쓰기
    job.setStatus(PUBLISHED); 
    jobRepository.save(job); // SUCCESS가 PUBLISHED로 변하는 정합성 오류 발생
});


이유

Pub/Sub 구독 메시지 응답이 DB 쓰기 보다 빠른 경우

  • 정상 흐름: Pub/Sub 게시 -> 게시 완료 변경(DB: PUBLISHED) -> 구독 메시지 수신(DB: SUCCESS)
  • 비정상 흐름: Pub/Sub 게시 -> 구독 메시지 수신(DB: SUCCESS) -> 게시 완료 변경(DB: PUBLISHED)


의견

병렬 또는 비동기로 외부와 통신하고 상태를 업데이트 하는 부분들은 이전에도 비슷한 이슈([Javascript] forEach에서 async await가 순차적으로 수행되지 않는 경우)가 있었는데 매번 주의해서 개발해야하는 거 같다.


Environment and Prerequisite

  • Pub/Sub
  • RDB
  • Java


Background

  • While processing list in parallel to publish Pub/Sub events, an issue occurred where the final state in the database was saved differently than intended.
  • Data inconsistency is occurring even though all database write logs appear normal.


Issue

  • Issues occurred in the logic that uses parallelStream() to send bulk messages and batch update their statuses.
  • Although the system received a “Processing Succeeded (SUCCESS)” response from GCP Pub/Sub and updated the DB, the final result remained in the “Published (PUBLISHED)” state.
  • The following pseudo-code illustrates the logic where the issue occurred.
// 1. Parallel event publishing (Main Thread)
jobList.parallelStream().forEach(job -> {
    // Publishing Pub/Sub messages
    publishEvent(job); 
});

// ---------------------------------------------------------
// [Key Point] The SUCCESS response from the Pub/Sub subscrition arrives first!
// A separate subscription thread (Sub Thread) has already updated the DB to SUCCESS.
// ---------------------------------------------------------

// 2. Status update after publishing (Main Thread)
// This runs late and overwrites the DB with "PUBLISHED"
jobRepository.findAllById(ids).forEach(job -> {
    // AS-IS: Unconditional overwrite without checking the current status
    job.setStatus(PUBLISHED); 
    jobRepository.save(job); // Integrity error: SUCCESS reverts to PUBLISHED
});


Reason

Pub/Sub subscription response arriving faster than the DB write

  • Expected Flow: Publish to Pub/Sub -> Change to “Published” (DB: PUBLISHED) -> Receive Subscription Message (DB: SUCCESS)
  • Abnormal Flow: Publish to Pub/Sub -> Receive Subscription Message (DB: SUCCESS) -> Change to “Published” (DB: PUBLISHED)


Thoughts

I have encountered similar issues before regarding parallel or asynchronous processing and state updates ([Javascript](EN) async await is not work sequentially in forEach). It seems this is a recurring pattern that requires constant care during development.


환경

  • Docker


배경

  • Docker 빌드 시 아래와 같은 문구를 보여주며 빌드 에러 발생.
Error response from daemon: client version 1.24 is too old.


원인

Docker 빌드 시 아래와 같은 요청으로 진행

  • Docker CLI(Client)가 빌드를 Docker Daemon(Server)에 요청.
Docker CLI -> Docker Daemon

Docker Daemon 허용하는 버전이 낮아서 오류 발생

  • Docker CLI(Client)가 요청한 API 버전이 Docker Daemon(Server)에서 허용하는 최소 버전보다 낮아서 발생.
Docker CLI -[Use API version 1.24]-> Docker Daemon


해결 방법

  • 아래와 같은 파일을 /etc/docker/daemon.json 작성 후 sudo systemctl restart docker로 재시작 진행.
{
  "min-api-version": "1.24"
}


의견

여러 방법이 있지만 해당 방법은 웹에서 흔히 찾을 수 있는 해결방법이 아니었고 AI도 해당 방법을 나중에야 알려줬으나 가장 간단하게 보여 이 방법으로 해결했다. 당연히 일시적인 방법이며 버전을 올리는게 더 장기적으로 맞는 방법 같다.


Environment and Prerequisite

  • Docker


Background

  • A build error occurred during the docker build process with the following message.
Error response from daemon: client version 1.24 is too old.


Cause

Docker Build Request Process

  • The Docker CLI(Client) sends a build request to the Docker Daemon(Server).
Docker CLI -> Docker Daemon

Version Mismatch in Docker Daemon

  • This error occurs when the API version requested by the Docker CLI(Client) is lower than the minimum version allowed by the Docker Daemon(Server).
Docker CLI -[Use API version 1.24]-> Docker Daemon


Solution

  • Create or edit the /etc/docker/daemon.json file with the following configuration, then restart the Docker service using sudo systemctl restart docker.
{
  "min-api-version": "1.24"
}


Opinion

While there are several ways to solve this, this specific solution wasn’t easily found on the web. Even AI suggested it only after some digging. However it seemed to be the most straightforward fix so I used it. Of course this is a temporary workaround. Upgrading the client version would be the more appropriate long term solution.

요즘 검색을 거의 안하고 AI에 의존하는 나의 개인적 고백

목차


검색 대신 AI를 여는 일상

기술 블로그를 좋아하고 글 쓰는 걸 좋아하는 사람이지만 최근 생성형 AI가 발전하고 나서 검색을 거의 안 하고 웹 문서에는 거의 안 들어가고 있다.

아니 검색할 필요와 시간 없이 AI에 질문하면 너무도 정리를 잘해준다. 가끔 hallucination이 있어서 거짓 정보를 준다고 하지만 항상 경계하고 있어서 불분명할 때는 출처를 달라고 하고 매번 검증해서 읽으니 이런 부분은 최근에는 잘 피해 가는 거 같다.


AI가 가져온 생산성

요즘의 AI들은 성능도 많이 올라왔고 생성형 AI를 2개 동시에 쓰니까 나름 교차 검증도 된다.

작년과 올해 AI를 사용하면서 꽤나 많은 위기의식을 느꼈다. 프롬프트를 잘 사용하면 코드는 이제 AI가 너무도 잘 만들어주고 정형화된 답이 있는 부분들은 AI가 생산성을 엄청 늘렸다.


블로그 유입 감소

블로그 유입이 꾸준하게 줄고 있다. 물론 글 쓰는 양도 적어지고 있지만 AI 발전의 영향도 있는 거 같다. 요즘 엔지니어들은 AI를 더 많이 이용하기에 검색을 통해서 들어오는 유입이 줄어들었다.


변화된 모습

사실 솔직히 이야기하면 나조차도 타이핑하지 않아도 찾을 수 있는 내 블로그 내용이 아니라면 다 AI에 먼저 물어보는 거 같다.

어차피 AI도 데이터 원천이 있어야 학습을 하고 이용할 수 있기에 글의 가치가 있지만, 생산성이 중요한 모든 분야에서는 이제 검색보다는 AI를 사용하는 게 더 일상화되어가는 거 같다.


앞으로의 방향

이런 시점에서 내 스타일도 변한 게 있다면 기존에는 간단한 사용법이나 기술적인 가이드도 만들었었지만 이제 그 영역은 AI가 충분히 대체 가능할 거 같고 개인의 의견이나 생각 또는 경험을 쓰는 방향으로 가야 할 거 같다.