포스트

락, 캐시, 메시지 큐, 비동기 처리 언제 써야 할까?

락, 캐시, 메시지 큐, 비동기 처리 언제 써야 할까?

들어가며

백엔드 공부를 하다 보면 한 번쯤은 이런 고민을 하게 된다.

“이 상황에서 락을 써야 하나?”
“캐시를 붙이는 게 맞나?”
“MQ까지 도입해야 할까?”
“이거 비동기로 돌리는 게 더 나은 거 아닌가?”

처음에는 개념은 알겠는데 언제 써야 하는지 감이 잘 안 잡혔다.
그래서 실제 상황 기준으로 정리를 해봤다.


락(Lock)은 언제 필요한가?

1. Race Condition이 발생할 때

여러 쓰레드가 동시에 같은 데이터를 건드릴 때다.

예를 들어:

  • 재고: 10개
  • 쓰레드 A, B가 동시에 재고 -1 수행

예상 결과 : 8
실제 결과 : 둘 다 10을 읽고 재고를 9로 업데이트

데이터 정합성 깨짐


2. 원자성(Atomicity)이 깨질 수 있을 때

대표적인 케이스:

  • 계좌 이체
    (A에서 돈 빼고 → B에 넣기)

중간에 끊기면?

  • A에서는 돈 빠짐
  • B에는 돈 안 들어감

그래서 위의 경우에는 하나의 트랜잭션 + 락으로 묶어야 한다.


락 쓸 때 고민해야 할 것

1. 비관적 락 vs 낙관적 락

종류특징
비관적 락일단 잠그고 시작 (안전하지만 느림)
낙관적 락충돌 없다고 가정 (빠르지만 재시도 필요)

트래픽 많고 충돌 적으면 → 낙관적 락
금융/정합성 중요 → 비관적 락


2. 데드락

서로 락 기다리다가 둘 다 멈추는 상황


3. 락 범위

  • 너무 큼 → 성능이 안 좋아짐
  • 너무 작음 → 관리 힘들어짐

적당한 범위를 제한 하는것이 중요


한 줄 정리

“여러 쓰레드가 같은 데이터를 건드리고 그 데이터가 정확해야 하면 락을 사용하자”


캐시는 언제 써야 할까?

1. 같은 요청이 반복될 때

예시:

  • 인기 검색어
  • 카테고리 목록
  • 유저 프로필

매번 DB 때리는 건 비용이 크다 캐시에 올려두면 끝


2. 원본 접근 비용이 비쌀 때

  • 외부 API 호출
  • 복잡한 통계 쿼리
  • 대용량 DB 조회

디스크 / 네트워크는 메모리보다 압도적으로 느림 Redis 같은 캐시로 해결


3. 잘 안 바뀌는 데이터일 때

  • 공지사항
  • 약관
  • FAQ

조회는 많고 변경은 거의 없다.


캐시의 문제

1. Cache Invalidation

“원본 바뀌면 캐시는 어떻게 할까?”

틀린 데이터 계속 참조한다


2. TTL 설정

  • 너무 길면 → 데이터 틀림
  • 너무 짧으면 → 캐시 의미 없음

3. 메모리 한계

  • 어떤 걸 버릴지 결정 필요
    • 가장 오랫동안 참조되지 않은 데이터를 캐시에서 교체(LRU)
    • 참조 횟수가 가장 적은 페이지를 교체(LFU)

한 줄 정리

“자주 조회되고 잘 안 바뀌고 다시 가져오기에 비용이 비싸다면 캐시를 사용하자”


메시지 큐는 언제 필요할까?

1. 서비스 간 결합도 줄일 때

문제 상황:

  • 주문 → 결제 → 알림

결제가 실패하면 주문도 같이 실패한다.


해결:

  • 메시지 큐 도입 주문 서비스(Producer):

    주문을 끝내고 큐에 메시지를 보낸다.

결제 서비스(Consumer):

자신의 상태와 처리 능력에 맞춰 자율적으로 메시지를 가져간다.

시스템 전체가 훨씬 유연해짐


2. 트래픽 폭주 대응

예시:

  • 티켓팅
  • 수강신청

서버 처리량: 초당 1000 요청: 초당 10000


해결:

  • 메시지 에 쌓아둔다.
  • 서버는 처리 가능한 만큼만 소비한다.

시스템이 다운되지 않는다


3. 비동기 처리용

예시:

  • 회원가입 후 이메일 발송
  • 영상 인코딩

사용자 입장에서 지금 필요 없음 큐에 던지고 나중에 처리


메시지 큐의 단점

1. 메시지 유실

큐 죽으면 데이터 날아간다. 큐나 메시지의 속성을 지정하여 영속성을 보장해줘야한다.


2. 순서 보장

주식 주문 같은 건 순서 중요 설계 난이도 올라간다.


3. 중복 처리

메시지 두 번 올 수 있음 반드시 멱등성(Idempotency) 확보해야 한다.


한 줄 정리

“상대 서비스 믿을 수 없거나 트래픽 폭주하거나 지금 당장 안 해도 되면 메시지큐를 사용하자”


비동기(Async)는 언제 쓰면 좋을까?

1. I/O 작업이 많을 때

  • DB 쿼리
  • 외부 API
  • 파일 처리

대부분 “기다리는 시간” 동기로 하면 쓰레드 낭비 비동기로 하면 다른 일 계속 가능


2. UX 개선이 필요할 때

동기

회원가입 → 이메일 발송 → 응답 (3초 걸림)

비동기

1
2
회원가입 ----------→ 응답
        ↘ 이메일 발송

3. 무거운 작업 분리

  • 이미지 리사이징
  • 엑셀 생성
  • 리포트 생성

메인 쓰레드에서 하면 다른 요청 다 밀림


비동기의 단점

1. 설계 복잡도 증가

  • 실패 시 재시도?
  • 완료 알림?

2. 데이터 일관성 문제

  • 메인은 성공
  • 비동기 실패

최종 일관성 설계 필요


3. 디버깅 어려움

실행 흐름이 서로 다른 스레드나 시점에 분산되어 있어 추적 힘들다.


한 줄 정리

“쓰레드를 기다림에 있지 말고 계속 일하게 만들고 싶다면 비동기를 사용하자”


최종 요약

기술언제 쓰는가
데이터 정확성이 최우선일 때
캐시자주 조회 + 변경 적음 + DB 조회 비용 클때
메시지큐서비스 분리 / 트래픽 버퍼 / 비동기
비동기기다림 줄이고 처리량 늘릴 때

마무리

이 네 가지는 결국 성능과 데이터 무결성 사이의 트레이드오프를 해결해주는 기술들이다.

  • 락 → 정확성
  • 캐시 → 속도
  • 메시지큐 → 안정성
  • 비동기 → 효율

특정 기술을 선택해서 하나만 사용하는게 아니라 적절한 조합으로 서로 다른 가치를 극대화 하는것이 핵심인 것 같다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.