본문 바로가기
Develop/etc

[백엔드 실무 스터디] 5, 6, 7. 비동기, 동시성, I/O 병목 제어

by 연로그 2025. 8. 17.
반응형

서론

이 글은 '주니어 백엔드 개발자가 반드시 알아야 할 실무 지식' 책을 읽고 진행하는 스터디 내용을 정리한다. 책을 읽고 학습하는 게 아니라, 책의 내용을 주제로 경험을 공유하는 스터디이기 때문에 포스팅 내용은 책과 관련이 없다. 이번 글은 '5장 비동기 연동, 언제 어떻게 써야 할까', '6장 동시성, 데이터가 꼬이기 전에 잡아야 한다', '7장 IO 병목, 어떻게 해결하지'를 읽고 진행한 스터디 내용을 정리했다. '(경험 공유)' 혹은 '(생각 공유)' 표기는 스터디원들이 실무에서 겪은 개인적인 경험이나 생각을 정리한 것이며, 항상 정답은 아니다.

 

 


5장 비동기 연동, 언제 어떻게 써야 할까

 

(경험 공유) 비동기 적용 사례

  • 병렬 처리를 위한 코루틴 적용
  • 알림톡 발송
  • 카프카에서 이벤트 컨슘 시 사용
    • ack 처리 후, 로직 수행은 비동기로 처리
    • 준실시간 유지 필요하기 때문에 lag이 많이 쌓이면 안 되는 상황
    • 실패하면 로그 내용을 확인하며 재수행
  • 대량 삭제 처리 시 비동기 진행
    • 어드민 기능 → API 호출 → Jenkins 잡 수행 (이 부분을 비동기 처리)
    • Jenkins 잡 수행 시간이 길어서 비동기로 처리
    • 잡 수행 실패하면 젠킨스 잡 수동으로 재실행

 

 

롤백이 안돼요 (122p)

  • 책 내용: @Transactional을 사용한 코드 내부에서, 비동기로 실행했더니 예외 발생해도 실패가 발생하지 않음
  • (생각 공유) 반드시 하나의 트랜잭션 내에서 수행이 필요한 작업이라면 비동기를 지양해야 한다고 생각

 

 

카프카 vs 레디스 pub/sub (125p)

  • (생각 공유) 카프카, 레디스 둘 다 사용 중이면 뭘 사용할지 판단 기준이 뭘까?
    • 개인적으로는 다른 서버와 통신이 필요하면 카프카 선호
    • 바로 처리해야하는 케이스, 간단하게 사용 가능한 케이스는 레디스 선호
    • 레디스는 싱글 스레드이니, lag이 많이 쌓이는 케이스에 사용하면 이슈 발생할 듯
    • 레디스는 메시지를 따로 저장하지 않아, 안정성이 떨어질 수 있음
  • (경험 공유) 레디스 pub/sub 적용 사례
    • 로컬 캐시 파기를 위해 적용

 

 

메시지 전송 처리 (124p)

  • (생각 공유) 메시지 전송이 좋은 케이스
    • 재처리가 반드시 필요할 때
    • 서버간 의존성을 낮추고 싶을 때, 수용할 수 있는 트래픽 양이 다를 때
    • 여러 서버에 메시지 제공이 필요할 때
  • (경험 공유) 메시지 도입하려 했던 사례
    • 이벤트 컨슘 시 다른 서버의 internal-api 호출하는데, internal-api 수행이 오래 걸림
      • internal-api 호출 시 타임아웃 처리 → 이벤트 처리 실패
      • 실제로는 internal-api 로직 수행이 성공
    • internal-api 호출 대신 카프카 메시지 전송 & 컨슘 구조 도입 고려
      • internal-api에서 DB CUD작업이 많아서 긴 작업시간이 불가피함
      • internal-api timeout 설정 변경도 고려하였으나, 케이스마다 수행 시간이 상이 (정말로 문제가 있는 타임아웃인지, 단순히 수행 시간이 오래 걸리는 타임아웃인지 구분이 힘듦)
      • 반드시 한번 수행하기만 하면 되고, 어느 시점에 수행되어야 하는지는 중요하지 않음
  • (생각 공유) MSA와 EDA 붐이 일면서 불필요하게 많이 사용되는 케이스가 많은 것 같다
  • (경험 공유) 데이터 변경은 거의 없으나, 트래픽이 많아서 불필요하게 API 콜을 자주 하는 상황이라 이벤트 적용하고 싶음
    • 캐싱하면 안되는가? → 데이터가 변경 시 실시간으로 반영 필요

 

메시지 재처리 (127p)

  • (경험 공유) 순서가 있는 이벤트 재처리
    1. 주문 시 이벤트가 A → B → C 순으로 발생한다
    2. B 이벤트 처리하다 이슈 발생 시 DLT로 전송하고, 주문 번호를 Redis에 저장
    3. C 이벤트 처리 시, Redis에 저장한 주문번호와 같은 이벤트면 DLT로 전송
    4. DLT 재수행 시 DLT에 쌓인 순서대로 처리됨 (B, C)

 

 

트랜잭션 아웃박스 패턴 (134p)

  • 메시지 데이터가 유실되지 않도록 보장하기 위해, 해당 데이터를 DB에 저장
  • 저장된 메시지를 읽어 메시징 시스템에 전송
  • (경험 공유) CDC + 트랜잭션아웃박스 패턴 사용 사례
    • 트랜잭션을 완벽하게 지키자는 의도에서 도입
    • 아키텍쳐 구조가 불필요하게 복잡해져 구조를 단순화하는 작업이 필요하게 됨
    • 결국 트랜잭션아웃박스가 유용하게 쓰일 일이 없었음
    • 정합성이 완전히 일치해야 하는, 정산 관련 팀에서 사용하지 않을까 추측

 

 

배치 전송 (139p)

  • (경험 공유) 파일 전송 사례
    • 데이터 집계하여 타회사에 전송해야 하는 상황
    • json으로 전송하기는 너무 거대하고 보안 이슈가 있을 수 있어 파일로 전송
    • ftp(=파일 전송 프로토콜)을 이용해 통신

 

 

CDC (142p)

  • CDC 적용한 케이스
    • (경험 공유) 실시간 연동이 필요한 경우
    • (생각 공유) 서버 간의 통신이 필요하다면 이벤트 전송이 깔끔하지 않을까?
      • 너무 많은 곳에서 수정되는 경우, 모든 곳에 publish 코드 넣기 어려울 수 있음
  • (경험 공유) 서버 개발자가 직접 CDC 적용이 불가, DBA에게 요청 필요

 

 


6장 동시성, 데이터가 꼬이기 전에 잡아야 한다

 

동시성/비동기 이슈 처리 (150p)

 

@Async와 함께 사라지다 (feat. TaskDecorator)

목차 1. 스레드가 가진 데이터, ThreadLocal 2. 데이터가 사라졌어요 (예제코드) 3. 비동기와 사라진 데이터 3. ThreadLocal 유지하기 1. 스레드가 가진 데이터, ThreadLocal ThreadLocal는 각 스레드마다 별도의

yeonyeon.tistory.com

 

 

Atomic type (156p)

  • CAS 연산 & volatile 적용
  • (경험 공유) 배치에서 병렬처리 시, count 체크할 때 AtomicLong 활용

 

 


7장 IO 병목, 어떻게 해결하지

 

논블로킹 도입 (190p)

  • (생각 공유) 단순히 I/O 대기 때문에 도입한다면 반대하는 편
    • 로직 개선만으로 충분히 해결 가능한 이슈는 아닌가?
    • 상대 서버의 트래픽이 수용 가능한 상태인가?
    • 예외 처리는 어떻게 할 것인가?
    • 로깅 정보(ex: MDC 등)를 유실하지 않고 잘 유지하는 방법은?
    • 모든 외부 시스템 호출 시 논블로킹 호출을 보장할 수 있는가?
    • 해당 서버를 개발하는 모든 개발자가 논블로킹 시스템에 대한 충분한 이해가 있는가?

 

 

(생각 공유) Virtual Thread 사용의 고민

  • 외부 API 속도가 보장되는 경우 Virtual Thread 도입이 큰 의미가 있을지 의문
  • (경험 공유) 대부분 rpc 통신 중이라 통신 비용보다 직렬화&역직렬화 비용이 더 큼

 

 

(생각 공유) Virtual Thread의 pinned 이슈 (195p)

  • JDK 24부터 pinned 이슈가 해소되었다는 이야기가 있음
  • → 사실이 아님. synchronized 키워드로 인한 pinned 이슈는 해소되었으나, 모든 케이스에 대한 pinned 이슈가 해소된 것은 아님 (참고: https://openjdk.org/jeps/491)
 

JEP 491: Synchronize Virtual Threads without Pinning

JEP 491: Synchronize Virtual Threads without Pinning AuthorPatricio Chilano Mateo & Alan BatemanOwnerAlan BatemanTypeFeatureScopeImplementationStatusClosed / DeliveredRelease24Componenthotspot / runtimeDiscussionhotspot dash dev at openjdk dot org,

openjdk.org

 

반응형