Why It's Time to Retire CRUD

Table of Contents

1 [250107] Why it's time to retire CRUD

2 요약

  1. CRUD의 문제점
  2. Update와 Delete로 인한 데이터 영구 삭제/변경
  3. 규정 준수와 감사 요건 충족 어려움
  4. 과거 시점의 데이터 조회 불가능
    • 예: 특정 시점의 주식 가격
    • 예: 계정 해지 전 고객의 서비스 이용 내역
  5. 초기 해결방안

2.1 타임스탬프 방식

  • 업데이트 시 새로운 레코드 삽입
  • 시간 정보 컬럼 추가
  • 최신값 확인을 위한 추가 로직 필요

2.2 삭제 플래그 방식

  • 실제 DELETE 대신 플래그 사용
  • 별도의 테이블로 삭제 기록 관리
  • JOIN 작업 시 복잡도 증가
  • 진보된 해결방안

3.1 Temporal Tables

  • 데이터베이스 엔진 차원의 지원
  • 자동 이력 관리
  • 히스토리 테이블 자동 관리
  • 유효 시간만 추적 가능

3.2 Bitemporal 데이터베이스

  • 두 가지 시간 추적
    • Valid Time: 데이터 유효 시점
    • Transaction Time: 데이터 변경 시점
  • 운영 쿼리 정상 수행
  • 과거 데이터 조회 용이
  • 비즈니스/규정준수/감사 요구사항 충족

3 원문 번역

CRUD는 우리 사고방식에 깊이 자리잡고 있기 때문에 어떤 결함이 있는지 쉽게 인지하기 어렵다. 문제는 업데이트와 삭제 작업 모두 데이터를 파괴한다는 점이다. 삭제는 데이터베이스에서 데이터를 명시적으로 삭제하는 반면, 업데이트는 하나 이상의 레코드에 있는 값을 새 값으로 대체하므로 이전 값의 레코드가 모두 삭제한다.

이러한 파기가 왜 그렇게 문제가 될까? 이 문제를 해결하기 위해 조직은 지난 수년간 어떤 노력을 해왔을까? 그리고 가장 중요한 것은 지금 무엇을 해야 할까?

3.1 데이터 파기 문제

데이터가 더 이상 비즈니스에 현재 상태를 나타내지 않아도 보관해야 하는 경우가 있다.

데이터 규정 준수(Data Compliance)가 가장 큰 이유일 것이다. 규정에 따라 수년 동안 추적이 가능해야 한다. 언제 데이터를 감사하거나 특정 시점의 값을 묻는 일종의 포렌식 쿼리를 수행해야 할지 알 수 없기 때문이다.

나아가서 일반적으로 과거의 특정 시점에 데이터를 알고 싶어하는 비즈니스상 이유는 다양하다.

특정 날짜의 주식 가격, 고객이 계정을 해지하기 전에 어떤 서비스를 결제했는지? 목록은 끝이 없다.

또한 데잉터 규정 준수 요건은 '특정 시점의 값'을 넘어서는 것일 수도 있습니다. 특히 이 두 가지 질문에 대한 답변이 서로 다른 경우에는 '언제 값을 변경했는가'를 알고 싶을 수도 있습니다.

3.2 Logical Updates and Deletes with Timestamps and Flags

데이터 소멸 문제를 해결하기 위한 기본적인 접근 방식은 일부 작업이 레코드를 업데이트하거나 삭제한 후에도 데이터의 기록 값을 유지하는 이다.

기존 데이터를 업데이트하는 경우, 첫 번째 단계는 각 테이블의 타임스탬프 열을 통해 각 업데이트에 대한 시간 정보를 유지하는 것. 데이터베이스는 UPDATE를 수행하는 대신 INSERT를 수행하여 타임스탬프 열에 작업 시간을 기록한다. 이러한 유형의 작업을 '논리적 업데이트'라고 생각할 수 있다. 물론 쿼리가 과거 값에 대한 것이 아니라면 후속 SELECT 문은 항상 타임스탬프를 확인하여 가장 최근 값만 반환합니다.

삭제 플래그도 비슷한 방식으로 작동한다. 삭제 플래그를 사용하면 운영 데이터베이스에서 실제로 DELETE가 수행되지 않는다. 대신, 각 테이블의 추가 열에 레코드가 삭제된 것으로 간주되어야 함을 나타내는 플래그가 포함된다.

다른 상황에서는 관리자가 별도의 테이블을 설정하여 이러한 DELETE를 추적합니다. 이 경우 앱은 운영 데이터베이스에서 행을 삭제하고, 두 번째 테이블은 삭제된 행을 기록합니다. 따라서 삭제 플래그는 '논리적' 삭제를 제공하여 실제로 데이터베이스에서 데이터가 완전히 제거되지 않았음에도 불구하고 애플리케이션이 행을 삭제한 것으로 처리할 수 있도록 합니다.

논리적 업데이트와 삭제 모두 몇 가지 문제가 있습니다. 가장 중요한 것은 모든 애플리케이션 로직이 업데이트 및 삭제 시도 시뿐만 아니라 이후의 모든 SELECT에 대해서도 이를 지원해야 한다는 점입니다. 사소한 코딩 오류 하나로 인해 업데이트되거나 논리적으로 삭제된 행이 결과 집합에 잘못 반환될 수 있습니다.

둘째, JOIN이 포함되면 논리적 삭제는 엄청나게 복잡해집니다. 예를 들어, '고객'과 같은 비즈니스 엔터티가 여러 테이블의 데이터에 의존하고 있는데 조직에서 해당 고객을 삭제하는 경우, 각 개별 테이블에 삭제 플래그가 설정되어야 할까요? 아마도 아닐 것입니다.

3.3 Temporal Tables

논리적 업데이트 및 삭제의 문제를 해결하기 위해 일부 데이터베이스 빌트인으로 임시 테이블(Temporal Tables)을 제공한다.

이러한 'system-versioned' 임시 테이블에는 명시적으로 정의된 두 개의 타임스탬프 열이 있어 해당 테이블에 대한 전체 데이터 변경 기록을 유지합니다. 시스템(데이터베이스 엔진이라고도 함)은 테이블의 각 행에 대한 유효 기간을 자동으로 관리합니다.

임시 테이블에(Temporal Tables)는 임시 테이블과 일치하는 스키마를 가진 두 번째 테이블인 '기록(history)' 테이블에 대한 참조도 포함됩니다. 데이터베이스 엔진은 각 행을 업데이트하거나 삭제할 때마다 임시 테이블에 각 행의 이전 버전을 자동으로 저장합니다.

따라서 임시 테이블을 사용하면 데이터베이스 엔진이 데이터베이스 액세스 로직을 재작업할 필요 없이 논리적 업데이트와 삭제를 지원하는 무거운 작업을 자동으로 처리합니다.

3.4 From Temporal to Bitemporal

임시 테이블은 데이터베이스에 표시된 객체의 상태 변화, 즉 '유효(valid)' 시간을 추적하는 데 유용합니다. 예를 들어 특정 시점에 상품 가격이 1.00달러에서 2.00달러로 변경된 경우, 임시 테이블은 1.00달러 가격이 유효했던 시점과 2.00달러 가격이 유효했던 시점을 추적할 수 있습니다.

그러나 추적하지 않는 것은 해당 값을 변경한 트랜잭션이 언제 발생했는지입니다.

결국, 누군가 일주일 전에 가격을 변경하는 업데이트를 오늘 테이블에서 실행할 수 있습니다. 임시 테이블은 가격 변경 자체는 추적하지만 업데이트가 발생한 시점은 추적하지 않습니다.

XTDB와 같은 비시간적 데이터베이스는 이 문제를 해결합니다. 이러한 데이터베이스는 '유효한 시간'과 '거래 시간'을 모두 자동으로 추적하므로 '언제 가격이 1.00달러였나?“와 같은 쿼리는 물론 '누가 언제 가격을 변경했나?”와 같은 쿼리도 완벽하게 지원합니다.

3.5 The Intellyx Take (인텔릭스의 견해)

지금까지 파괴적인 데이터 운영 문제를 해결하기 위한 다양한 접근 방식이 사람들의 예상보다 더 복잡했다는 것이 이 이야기의 교훈입니다.

한 가지 해결책을 찾으면 또 다른 문제가 발생하는 식으로, 개발자들은 어느새 유지관리와 성능에 영향을 미치는 복잡한 코드를 대량으로 작성하게 되었습니다.

비시간적 데이터베이스는 유효 시간 및 트랜잭션 시간을 자동으로 추적하여 이러한 문제를 해결합니다.

비즈니스 운영에서 발생하는 일상적인 작업인 운영 쿼리는 정상적으로 수행됩니다.

비즈니스, 규정 준수 또는 포렌식 목적 등 과거의 일부 값에 대한 쿼리도 간단합니다.

Date: 2025-01-07 Tue 00:00

Author: Younghwan Nam

Created: 2025-02-20 Thu 14:08

Emacs 27.2 (Org mode 9.4.4)

Validate