Home 대량 쓰기 작업에서의 멱등성은 어떻게 보장할까?
Post
Cancel

대량 쓰기 작업에서의 멱등성은 어떻게 보장할까?

글을 작성하게 된 계기


회사에서 대량의 데이터를 쓰기 작업 하면서 멱등성 있게 처리 하는 방법에 대해 고민하게 되었고, 이 과정에서 알게 된 내용을 정리하기 위해 글을 작성하게 되었습니다.





1. 왜 멱등성이 필요할까?


대량 데이터를 다루는 작업에서는 종종 네트워크 오류, 시스템 장애, 휴먼 에러 등의 이유로 일부 요청이 실패하는 상황이 발생합니다. 이런 경우에는 실패한 부분만 선별적으로 다시 처리 할 수도 있지만, 상황에 따라 전체 데이터를 처음부터 다시 처리해야 하는 경우 도 있습니다. 이때 멱등성이 보장되지 않는다면, 이미 성공했던 작업이 중복으로 처리되는 문제가 발생할 수 있습니다.

Idempotence is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application.



즉, 멱등성이 대량 쓰기 작업에서 중요한 이유는 단순히 중복 요청을 막는 것이 아닌, 장애나 부분 실패 상황에서 안전하게 재시도하거나 전체를 다시 처리할 수 있는 기반 이 되기 때문입니다. 동일한 요청을 몇 번 수행해도 결과가 변하지 않는다는 보장이 있어야, 시스템은 실패한 작업이나 전체 작업을 안심하고 다시 시도할 수 있고, 이를 통해 데이터의 일관성신뢰성 을 유지할 수 있겠죠.

  • 동일한 요청을 몇 번 수행해도 결과가 변하지 않는다는 보장
  • 장애나 부분 실패 상황에서 안전하게 재시도하거나 전체를 다시 처리할 수 있는 기반







2. 멱등성을 보장하는 방법


멱등성을 보장하는 방법에는 여러 가지가 있지만 그중 데이터베이스 레벨 에서 사용할 수 있는 대표적인 방법에 대해 살펴보겠습니다.

  1. UNIQUE 제약 조건
  2. INSERT IGNORE
  3. INSERT … ON DUPLICATE KEY UPDATE
  4. 파일 데이터 멱등성



2-1. UNIQUE 제약 조건

데이터베이스 테이블에 특정 칼럼 또는 칼럼 조합에 대해 UNIQUE 제약 조건을 걸어 중복 데이터를 사전에 차단하는 방식입니다. 이미 존재하는 값이 들어오면 데이터베이스가 에러를 발생시켜 중복을 방지할 수 있습니다. 이는 데이터베이스 차원에서 일관성을 강하게 보장해 주기 때문에 가장 간단하고 확실한 방법으로, 다른 방법들과 함께 사용됩니다. 그러나 인덱스가 필요하고, 데이터 구조 설계에 영향을 주는 단점이 있습니다.

1
2
3
4
5
6
CREATE TABLE product
(
    id           BIGINT AUTO_INCREMENT PRIMARY KEY,
    product_code VARCHAR(50)  NOT NULL UNIQUE,          # UNIQUE 제약 조건
    name         VARCHAR(100) NOT NULL
);




2-2. INSERT IGNORE

INSERT IGNORE를 사용하면 UNIQUE 제약 조건이 걸려 있는 컬럼 에 대해 중복된 값이 들어오더라도 에러를 발생시키지 않고 무시하며 넘어갈 수 있습니다. 즉, 중복 데이터가 들어와도 삽입이 되지 않으며, 전체 구문이 실패하지 않고 처리가 계속됩니다. 단, 삽입 성공 여부를 명확하게 알기 어렵고, 무시된 건에 대해 별도 로깅이 필요할 수 있습니다.

1
2
INSERT IGNORE INTO product (product_code, name)
VALUES ('P001', '사과');




2-3. INSERT … ON DUPLICATE KEY UPDATE

INSERT … ON DUPLICATE KEY UPDATE 구문은 삽입하려는 데이터가 이미 존재하는 경우, 자동으로 업데이트로 대체하는 방식입니다. 하나의 쿼리로 INSERT와 UPDATE를 모두 처리할 수 있어 편리하며, 중복 데이터에 대해 유연하게 대응할 수 있습니다.

1
2
3
INSERT INTO product (product_code, name)
VALUES ('P001', '사과')
ON DUPLICATE KEY UPDATE name = '신규 사과';



그러나 잘못 사용하면 의도치 않은 값이 덮어씌워질 수 있기 때문에 주의가 필요합니다. 추가로 변경 이력 관리나 추가적인 로직이 필요한 경우에는 Trigger와 함께 사용하여 자동으로 로그를 남기거나 부가 작업을 처리할 수도 있습니다.

1
2
3
4
5
6
7
8
9
DELIMITER $$
CREATE TRIGGER trg_product_update
AFTER UPDATE ON product
FOR EACH ROW
BEGIN
    INSERT INTO product_log (product_code, old_name, new_name)
    VALUES (OLD.product_code, OLD.name, NEW.name);
END$$
DELIMITER ;




2-4. 파일 데이터 멱등성

대량 데이터를 이관할 때, MySQL에서 LOAD DATA INFILE 구문을 사용하여 데이터를 빠르게 삽입할 수 있습니다. 그러나 이 경우에도 멱등성을 보장하기 위해 중복 체크가 필요합니다. 이 경우도 마찬가지로 UNIQUE 제약 조건과 INGORE 옵션을 사용하면 중복된 데이터를 무시하고 삽입할 수 있습니다.

1
2
3
4
5
6
LOAD DATA INFILE '/path/to/product.csv'
INTO TABLE product
FIELDS TERMINATED BY ',' 
LINES TERMINATED BY '\n'
(product_code, name)
IGNORE 1 LINES;







3. 정리


대량의 데이터를 쓰는 작업은 단순해 보이지만, 실제로는 장애나 재처리 상황에서 매우 복잡해질 수 있습니다. 일부만 실패하거나 전체를 다시 처리해야 할 때를 대비해, 멱등성을 어떻게 보장할 것인지 미리 고민해 두는 것이 중요합니다. 이 외에도 REPLACE INTO 등 다양한 방법이 있는데, 상황에 맞게 잘 사용해봅시다.

MySQL을 예를 들어 설명했지만, 다른 데이터베이스에서 명칭만 다를 뿐 비슷한 방법이 존재합니다.


This post is licensed under CC BY 4.0 by the author.

감사 이력 관리 방법 비교

올바른 장애 대응 문화에 대한 생각 정리