전체 글

문제를 해결하기 위해서는 먼저 이해해야 한다.
카테고리 없음

풀스택 & 커리어 계획 (작성중)

보호되어 있는 글입니다.

A. 데이터 정합성/2. DB 내부 동작

[데이터 정합성] 10. 동시성 문제는 어떻게 해결할까? (2PL, MDL, Deadlock)

10. 데이터 정합성) 동시성 문제는 어떻게 해결할까? (2PL, MDL, Deadlock)앞 글에서는 하나의 트랜잭션이 Commit되는 과정과, 장애가 발생해도 데이터를 복구할 수 있는 이유를 살펴봤다. 그렇다면 트랜잭션만 사용하면 데이터 정합성은 항상 보장될까? 각 트랜잭션은 모두 정상적으로 Commit되더라도, 여러 트랜잭션이 동시에 같은 데이터를 수정하면 재고가 음수가 되거나 주문 수량이 잘못 계산되는 등 의도하지 않은 결과가 만들어질 수 있다. 이번 글에서는 Lock이 여러 트랜잭션의 실행 순서를 어떻게 조율해 데이터 정합성을 보장하는지 살펴보자. 1. 왜 Lock이 필요할까?다음과 같이 계좌의 잔고를 차감하는 출금 로직이 있다고 가정해 보자.@Transactionalpublic void wit..

A. 데이터 정합성/2. DB 내부 동작

[데이터 정합성] 9. InnoDB는 Commit을 어떻게 처리할까? (Redo Log, WAL, Doublewrite Buffer)

9. 데이터 정합성) InnoDB는 Commit을 어떻게 처리할까? (Redo Log, Undo Log, WAL)지금까지는 Spring과 JPA 관점에서 트랜잭션이 어떻게 동작하는지 살펴보았다.@Transactionalpublic void createOrder(...) { orderRepository.save(order); pointRepository.save(point);}보통 commit()이 호출되면 데이터가 바로 데이터 파일(.ibd)에 저장된다고 생각하기 쉽다. 하지만 실제로는 commit()이 완료되더라도 데이터 파일에는 아직 반영되지 않았을 수도 있다. 그렇다면 데이터 파일에 기록되기 전에 서버가 종료되면 Commit된 데이터는 어떻게 보장될까? 이번 글에서는 commit() 이후..

A. 데이터 정합성/4. 분산 시스템

[데이터 정합성] 8. 분산 시스템에서는 조회를 어떻게 설계할까? (CQRS)

[데이터 정합성] 8. 분산 시스템에서는 조회를 어떻게 설계할까? (CQRS)앞선 글에서는 Saga를 이용해 주문, 결제, 배송처럼 여러 서비스에 걸친 쓰기(Write) 작업의 데이터 정합성을 유지하는 방법을 알아보았다. 하지만 사용자가 실제로 보는 것은 쓰기(Write) 결과가 아니라 조회(Read) 화면이다. MSA에서는 주문, 결제, 배송 데이터가 각각 다른 서비스와 DB에 저장된다. 따라서 하나의 주문 상세 화면을 보여주기 위해서는 여러 서비스를 함께 조회해야 한다. 그렇다면 이러한 조회는 어떻게 설계하는 것이 좋을까? 조회 시점에 조합하기가장 단순한 방법은 조회 요청이 들어올 때마다 필요한 서비스를 호출해 데이터를 조합하는 것이다.public OrderDetailDto getOrderDetail..

A. 데이터 정합성/4. 분산 시스템

[데이터 정합성] 7. 분산 환경에서는 트랜잭션을 어떻게 관리할까? (MSA, Saga, CAP)

[데이터 정합성] 7. 분산 환경에서는 트랜잭션을 어떻게 관리할까? (MSA, Saga, CAP)앞선 글에서는 @TransactionalEventListener, Outbox Pattern, 메시지 큐(MQ)를 이용해 이벤트를 안전하게 전달하는 방법을 알아봤다. 지금까지는 하나의 애플리케이션, 하나의 DB 환경만 가정했다. 하나의 DB에서는 @Transactional 하나로 데이터 정합성을 관리할 수 있었다. 그런데 서비스마다 DB가 다르다면 어떻게 될까? 예를 들어 주문, 결제, 배송이 각각 다른 DB를 사용한다면 하나의 @Transactional로 모두 묶을 수 있을까? 이처럼 여러 서버와 여러 DB가 함께 동작하는 환경을 분산 환경(Distributed System) 이라고 한다. 대표적인 구조가 ..

A. 데이터 정합성/3. 외부 시스템 연동

[데이터 정합성] 6. 이벤트는 어떻게 유실 없이 전달할까? (outbox, at-least-once)

[데이터 정합성] 6. 이벤트는 어떻게 유실 없이 전달할까?앞선 글에서는 @TransactionalEventListener와 @Async를 이용해 Commit 이후에 후속 작업을 실행하는 방법을 알아보았다. 이를 통해 트랜잭션이 성공한 이후에만 이벤트를 처리할 수 있고, 사용자 응답도 빠르게 반환한다. 하지만 이벤트는 여전히 애플리케이션 메모리에만 존재한다. DB Commit은 성공했지만, @Async 작업이 실행되기 전에 애플리케이션이 종료되면 이벤트는 그대로 사라질 수 있다.후속 작업을 수행해야 한다는 이벤트 자체가 유실될 수 있다. 그렇다면 이벤트도 주문 데이터와 함께 DB에 저장하면 어떨까? 이를 위해 등장한 것이 Transactional Outbox Pattern이다. 트랜잭션 아웃박스 패턴 (..

A. 데이터 정합성/3. 외부 시스템 연동

[데이터 정합성] 5. 외부 시스템과의 데이터 정합성은 어떻게 관리할까? (EDA)

[데이터 정합성] 5. 외부 시스템과의 데이터 정합성은 어떻게 관리할까?서비스가 커질수록 결제, Slack, 이메일 등 다양한 외부 시스템과 연동하게 된다. 하지만 외부 시스템은 DB와 같은 트랜잭션으로 묶을 수 없기 때문에, 단순히 API를 호출하는 것만으로는 데이터 정합성을 보장하기 어렵다. 따라서 외부 시스템을 연동할 때는 비즈니스 영향도와 시스템 특성을 함께 고려하여 호출 방식을 설계해야 한다. 외부 API와 트랜잭션결론부터 말하면 외부 API 호출은 가능한 한 DB 트랜잭션 안에서 수행하지 않는 것이 좋다. 그 이유는 크게 두 가지이다.첫째, 외부 시스템은 DB 트랜잭션에 참여하지 않으므로 함께 Rollback할 수 없다.둘째, 외부 API의 응답을 기다리는 동안 DB Connection과 Lo..

A. 데이터 정합성/1. 애플리케이션 트랜잭션

[데이터 정합성] 4. 트랜잭션은 어떻게 설계할까? (전파, 격리 수준)

[데이터 정합성] 4. 트랜잭션은 어떻게 설계할까? (전파, 격리 수준)트랜잭션은 어디까지 묶어야 할까?지금까지는 @Transactional이 내부에서 어떻게 동작하는지 살펴보았다. Proxy가 트랜잭션을 시작하고, 같은 Connection을 사용하며, JPA는 Flush와 Dirty Checking을 통해 SQL을 생성한다. 하지만 실제로 트랜잭션을 만들 때 고민해야할 지점은 어디까지를 트랜잭션으로 묶어야할까? 이다.트랜잭션을 너무 크게 잡으면 작은 실패가 전체 작업을 실패시키고, 너무 작게 나누면 데이터 정합성이 깨질 수 있다.따라서 트랜잭션을 설계할 때 가장 먼저 고민해야 하는 것은 어떤 작업은 반드시 함께 성공해야 하고, 어떤 작업은 독립적으로 실패해도 되는지를 구분하는 것이다. 먼저 트랜잭션 경..

mint*
Minty Box