[DB] UNIQUE 제약조건 다시 보기

snowballnote·7일 전

Biz Assist에서 같은 공지를 여러 번 알리지 않게 만들면서
UNIQUE 제약조건을 사용했다.

CONSTRAINT uk_notification_delivery_dedup UNIQUE (
    channel,
    notification_type,
    source_code,
    external_id,
    content_fingerprint
)

UNIQUE가 뭐였지

UNIQUE는
특정 컬럼 값의 조합이 중복되지 않게 막는 제약조건이다.

예를 들어 위 코드는

채널
알림 유형
출처
공지 ID
내용 fingerprint

이 다섯 값의 조합이 똑같은 데이터는
두 번 저장할 수 없게 만든다.

왜 애플리케이션에서만 확인하지 않았을까

코드에서 먼저

이미 저장돼 있나?

를 조회한 다음 저장할 수도 있다.

근데 동시에 두 작업이 실행되면

A → 없음 확인
B → 없음 확인
A → 저장
B → 저장

처럼 둘 다 저장될 수 있다.

그래서 최종 중복 방지는
DB가 직접 맡도록 했다.

Biz Assist에서는 어떻게 썼나

알림 후보를 저장할 때
일단 INSERT를 시도한다.

try {
    jdbcTemplate.update(...);
} catch (DuplicateKeyException ignored) {
    return Optional.empty();
}

이미 같은 알림 이력이 있으면
DB의 UNIQUE 제약조건 때문에 저장이 실패한다.

그때 발생한 DuplicateKeyException을 잡아서

이미 만들어진 알림
→ 새 후보를 만들지 않음

으로 처리했다.

여러 컬럼을 묶어서도 UNIQUE를 만들 수 있다

처음에는 external_id 하나만 중복 방지하면 되는 줄 알기 쉽다.

근데 같은 공지라도
내용이 수정될 수 있다.

그래서 Biz Assist에서는

external_id
+
content_fingerprint

를 같이 사용했다.

같은 공지 ID라도 내용이 바뀌어
fingerprint가 달라지면 새로운 알림으로 볼 수 있다.

반대로 ID와 내용이 모두 같으면
중복 알림으로 막힌다.

PRIMARY KEY랑은 뭐가 다르지

둘 다 중복을 막지만 역할이 조금 다르다.

PRIMARY KEY
→ 행 자체를 식별하는 대표 키

UNIQUE
→ 특정 값이나 값의 조합이 중복되지 않게 제한

notification_delivery에서는

id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY

가 행을 구분하고

알림 중복 여부는 별도의 UNIQUE 제약조건이 담당한다.

다시 정리

UNIQUE
→ 중복되면 안 되는 값에 걸어두는 DB 제약조건

복합 UNIQUE
→ 여러 컬럼의 조합을 하나의 중복 기준으로 사용

DuplicateKeyException
→ UNIQUE 같은 제약조건 위반을 Java에서 처리할 때 사용 가능

Biz Assist에서는

같은 공지의 같은 내용을 두 번 알림 후보로 만들지 않기 위해 UNIQUE를 사용했다.

코드에서 중복을 검사하는 것도 필요하지만
마지막 중복 방지는 DB 제약조건에 맡길 수 있다는 걸 다시 봤다.

profile
개발자로 이 험난한 세상 살아가기

0개의 댓글