0Pricing
SQL Academy · 강의

이력을 보관해야 하는 이유

과거 데이터를 바탕으로 감사, 되돌리기, 분석을 수행합니다

이력을 보관해야 하는 이유은(는) CoddyKit의 무료 SQL Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 SQL Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. SQL Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

덮어쓰기의 문제

UPDATE 또는 DELETE를 실행할 때마다 이전 데이터가 영구적으로 사라집니다. 효율적처럼 보이지만 실제 문제가 생깁니다. 지난 화요일의 가격은 얼마였나요? 또는 이 레코드를 누가 언제 변경했나요?와 같은 질문에 답할 수 없게 됩니다.

이력을 유지한다는 것은 최신 버전 하나만이 아니라 행의 모든 버전을 저장하는 것입니다. 이 레슨에서는 이것이 중요한 이유와 SQL을 사용하여 이력을 보존하는 방법을 살펴봅니다.

이력을 보존해야 하는 세 가지 이유

데이터베이스에서 과거 데이터를 보존해야 하는 대표적인 이유는 세 가지입니다:

1. 감사 — 변경이 발생했다는 사실과 변경한 사람 및 시점을 증명합니다.
2. 실행 취소 — 전체 데이터베이스를 복원하지 않고도 실수를 되돌립니다.
3. 분석 — 과거에 대한 질문에 답하고, 추세를 파악하며, 기간을 비교합니다.

잘 설계된 이력 전략은 저장 공간을 지나치게 중복 사용하지 않으면서 세 가지 요구를 모두 충족합니다.

간단한 감사 테이블

가장 간단한 방법은 모든 변경 사항을 기록하는 별도의 감사 테이블을 만드는 것입니다. 각 행에는 이전 값, 새 값, 변경한 사람, 변경 시점이 저장됩니다.

아래는 products 테이블을 위한 감사 테이블입니다. operation 열에는 INSERT, UPDATE 또는 DELETE가 저장됩니다.

CREATE TABLE products_audit (
  audit_id   SERIAL PRIMARY KEY,
  product_id INT            NOT NULL,
  operation  VARCHAR(6)     NOT NULL,  -- INSERT / UPDATE / DELETE
  old_price  NUMERIC(10,2),
  new_price  NUMERIC(10,2),
  changed_by TEXT           NOT NULL,
  changed_at TIMESTAMPTZ    NOT NULL DEFAULT NOW()
);

감사 테이블 채우기

감사 테이블에 직접 기록할 수도 있지만, 가장 신뢰할 수 있는 방법은 데이터가 변경될 때마다 자동으로 실행되는 데이터베이스 트리거입니다. 이렇게 하면 어떤 애플리케이션 코드도 변경 기록을 우회할 수 없습니다.

여기서는 트리거를 다루기 전에 구조를 보여주기 위해 감사 행 하나를 직접 삽입합니다.

INSERT INTO products_audit (product_id, operation, old_price, new_price, changed_by)
VALUES (42, 'UPDATE', 9.99, 12.49, 'alice');

SELECT * FROM products_audit ORDER BY changed_at DESC LIMIT 5;

감사 추적 기록 읽기

감사 테이블에 행이 쌓이면 감사 관련 질문에 답하기 위해 조회할 수 있습니다. 아래 쿼리는 단일 제품의 전체 가격 이력을 최신순으로 보여줍니다.

SELECT
  changed_at,
  changed_by,
  operation,
  old_price,
  new_price
FROM products_audit
WHERE product_id = 42
ORDER BY changed_at DESC;

유효 날짜: 유효 시간 이력

감사 테이블은 변경을 수행한 시점(트랜잭션 시간)을 기록합니다. 때로는 현실 세계에서 어떤 사실이 참이었던 시점(유효 시간)도 추적해야 합니다.

주 테이블에 valid_from 및 valid_to 열을 추가하면 유효 시간 이력이 생성되며, 이를 서서히 변하는 차원(SCD 유형 2)이라고도 합니다.

CREATE TABLE employee_history (
  id          SERIAL PRIMARY KEY,
  employee_id INT            NOT NULL,
  department  TEXT           NOT NULL,
  salary      NUMERIC(10,2)  NOT NULL,
  valid_from  DATE           NOT NULL,
  valid_to    DATE           -- NULL means current record
);

-- Current record for employee 7
INSERT INTO employee_history (employee_id, department, salary, valid_from)
VALUES (7, 'Engineering', 85000, '2023-01-01');

서서히 변하는 레코드 갱신

직원이 부서를 옮기면 해당 행을 UPDATE하지 않습니다. 대신 valid_to를 설정하여 이전 행을 닫고, 종료 시점이 정해지지 않은 새 행을 삽입합니다. 이렇게 하면 전체 이력이 보존됩니다.

-- Step 1: close the current record
UPDATE employee_history
SET valid_to = '2024-06-01'
WHERE employee_id = 7 AND valid_to IS NULL;

-- Step 2: insert the new record
INSERT INTO employee_history (employee_id, department, salary, valid_from)
VALUES (7, 'Product', 90000, '2024-06-01');

-- Verify history
SELECT department, salary, valid_from, valid_to
FROM employee_history
WHERE employee_id = 7
ORDER BY valid_from;

특정 시점 조회

유효 시간 열이 있으면 특정 날짜에 무엇이 유효했는지를 물어볼 수 있습니다. 일반적인 UPDATE 방식으로는 불가능한 조회입니다.

WHERE 절은 대상 날짜가 행의 유효 기간 안에 포함되는지 확인합니다.

-- What department and salary did employee 7 have on 2023-09-15?
SELECT department, salary, valid_from, valid_to
FROM employee_history
WHERE employee_id = 7
  AND valid_from <= '2023-09-15'
  AND (valid_to > '2023-09-15' OR valid_to IS NULL);

시스템 버전 관리 시간 테이블

최신 SQL 데이터베이스(PostgreSQL 16+, SQL Server, MySQL 8)는 시스템 버전 관리 시간 테이블을 지원합니다. 데이터베이스가 숨겨진 열에 트랜잭션 시간을 자동으로 기록하며, 특수한 구문으로 과거 상태를 조회할 수 있습니다.

SQL Server 예시 — 데이터베이스 엔진이 달라도 개념은 같습니다:

-- SQL Server / MariaDB style (illustrative)
CREATE TABLE orders (
  order_id    INT PRIMARY KEY,
  status      VARCHAR(20),
  total       NUMERIC(10,2),
  SysStartTime DATETIME2 GENERATED ALWAYS AS ROW START,
  SysEndTime   DATETIME2 GENERATED ALWAYS AS ROW END,
  PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime)
) WITH (SYSTEM_VERSIONING = ON);

-- Query historical state
SELECT * FROM orders FOR SYSTEM_TIME AS OF '2024-01-15 12:00:00'
WHERE order_id = 100;

실행 취소에 이력 활용

이력 테이블은 읽기만을 위한 것이 아닙니다. 실수를 실행 취소하는 데도 사용할 수 있습니다. 일괄 작업으로 가격 데이터 500건이 손상되었다면 백업을 건드리지 않고 감사 테이블에서 복원할 수 있습니다.

-- Undo all price changes made by the bad batch job at a specific time
UPDATE products p
SET price = a.old_price
FROM products_audit a
WHERE p.id         = a.product_id
  AND a.operation  = 'UPDATE'
  AND a.changed_by = 'batch_job'
  AND a.changed_at BETWEEN '2024-03-10 02:00:00' AND '2024-03-10 02:05:00';

-- Confirm affected rows
SELECT COUNT(*) AS rows_restored FROM products_audit
WHERE changed_by = 'batch_job'
  AND changed_at BETWEEN '2024-03-10 02:00:00' AND '2024-03-10 02:05:00';

시간에 따른 분석

이력 데이터는 시계열 분석을 가능하게 합니다. 지표가 시간에 따라 어떻게 변화했는지 추적하고, 월별 수치를 비교하거나, 별도의 데이터 웨어하우스를 사용하지 않고도 이상을 감지할 수 있습니다.

이 쿼리는 감사 테이블을 사용해 각 달력 월의 제품 평균 가격을 보여 줍니다.

SELECT
  DATE_TRUNC('month', changed_at) AS month,
  ROUND(AVG(new_price), 2)         AS avg_price
FROM products_audit
WHERE product_id = 42
  AND operation IN ('INSERT', 'UPDATE')
GROUP BY 1
ORDER BY 1;

이해도 확인

SQL에서 이력 데이터를 저장하는 방법을 얼마나 이해했는지 확인해 보세요.

복습: 이력을 보존하는 이유

이 레슨에서는 데이터를 덮어쓰는 것이 왜 위험한지, 그리고 SQL 패턴으로 감사, 실행 취소, 분석을 위해 이력을 보존하는 방법을 배웠습니다.

핵심 내용:

  • 감사 테이블은 모든 INSERT, UPDATE, DELETE를 기록하며 누가 언제 수행했는지도 남깁니다.
  • 유효 시간(SCD 유형 2) 행은 valid_from / valid_to 열을 사용해 실제 세계의 시간 흐름을 기록합니다.
  • 특정 시점 조회는 해당 날짜 열을 기준으로 필터링하여 과거 상황에 대한 질문에 답합니다.
  • 시스템 버전 관리 시간 테이블은 데이터베이스 수준에서 트랜잭션 시간 추적을 자동화합니다.
  • 이력 데이터는 백업 없이도 정밀한 실행 취소와 풍부한 시계열 분석을 가능하게 합니다.

과거를 보존하는 것은 부담이 아닙니다. 신뢰할 수 있고 감사 가능한 시스템의 토대입니다.

자주 묻는 질문

“이력을 보관해야 하는 이유” 강의는 무료인가요?

네 — “이력을 보관해야 하는 이유” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 SQL Academy 강의 전체를 잠금 해제할 수 있습니다. SQL Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“이력을 보관해야 하는 이유”에서 뭘 배우나요?

과거 데이터를 바탕으로 감사, 되돌리기, 분석을 수행합니다 브라우저에서 직접 실행하는 실습 코드로 SQL Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

SQL Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 SQL Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“이력을 보관해야 하는 이유” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 SQL Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 SQL Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 이력을 보관해야 하는 이유
  2. 추가 전용 이벤트 테이블
  3. 시간 및 버전 관리 행
  4. 이벤트에서 상태 재구성하기
← SQL Academy(으)로 돌아가기