중복 추가 이슈를 해결하기 위한 고민

yeoni·2024년 12월 4일
0

한끼족보

목록 보기
2/4
post-thumbnail

메뉴 추가 동시성 이슈

요즘, 동시성에 대해 공부하면서, 이전에 만들었던 프로젝트에서 발생할 수 있는 동시성 문제들에 대해 찾아보고 해결방법을 고민하고 있다. '한끼족보' 프로젝트에서는, 여러 명의 사람이 동시에 같은 메뉴를 추가할 경우, 같은 메뉴가 하나의 테이블에 여러 개 저장되는 현상이 발생한다.

테이블 구조

고민한 해결방법

위의 문제를 해결하기 위해 고민한 방법은 2가지 이다.

  1. 유니크 키 제약조건
    (store_id, name) 컬럼 조합에 대해 복합 유니크 제약 조건을 걸어, 동시성 문제 해결하는 것이다.
    가장 간단한 해결 방법으로 DB 차원에서 중복 삽입을 자동으로 방지할 수 있다. 하지만 이 경우, DB단에서 발생하는 예외(유니크 키 제약 위반)를 service의 비즈니스 로직 상에서 try-catch 문을 통해 커스텀 예외를 던지도록 핸들링하는 작업이 필요하다. 여기서 바로 고민사항이 생겼는데, 개인적으로 DB단에서 발생하는 예외를 서비스 계층에서 잡는다는 것 자체가 어색하게 느껴졌다.
    또한 유니크 제약 조건을 생성했을 때, 발생하는 유니크 인덱스와 관련된 부수효과도 걱정이었다. 유니크 제약 조건을 걸게되면 자동으로 유니크 인덱스가 생기게 되고 동시 접근 상황일 때, 유니크 인덱스에서 중복된 값을 체크하는 과정에서 DB 락을 사용한다. 이 과정에서 데드락이 발생하는 상황이 빈번하다고 한다.
    또한, 외래키 제약 조건으로 인해 생긴 store_id 인덱스와 유니크 제약 조건으로 생긴 (store_id, name)조합의 인덱스가 생성됨에 따라 중복 인덱스 발생하게 된다. 다시 말해, store_id만 존재하는 인덱스는 사실상 필요가 없다. 후자의 인덱스로도 충분히 활용할 수 있기 때문이다. 인덱스가 불필요하게 많아지게 된다면, 이 또한 성능저하의 원인이 되기 때문에 이러한 이슈도 걱정이 되었다.

  2. Insert 쿼리를 사용하기전에 이미 저장된 메뉴인지 조회해, 있다면 Custom Exception을 발생
    두번째 방법으로 save하기 전에, select 쿼리를 날려서 이미 메뉴가 존재하는지 확인하는 방식이다. 현재 구현되어 있는 로직이지만, 동시성 처리가 따로 되어 있지 않다. 해당 방법은 비즈니스 로직 상에 작성하기 때문에 더 이해하기 쉽다는 장점이 있다고 생각했다.
    하지만, 로직 수행에 있어 select쿼리를 한 번 더 발생시킨다는 단점과 동시성 이슈에서 자유롭지 못하기 때문에 따로 동시성을 해결해주기 위해, 로직을 작성해주어야 한다는 단점이 존재했다. DB 단에서 중복 삽입을 막지 않는다는 것도 과연 맞는 방법인지 의문이었다. 후에 찾아보니, 첫번째 걱정의 경우 단건 쿼리 한방은 성능에 끼치는 영향이 거의 미미하다고 하다는 것을 알게 되어 성능 차원의 걱정은 하지 않아도 될 듯 하다. (암달의 법칙)


둘 중 무엇이 좋은 방법일까 계속 고민을 하였고, 혼자서는 답을 찾을 수 없어 여러 주변 친구들과 현직자 분들께 조언을 구하였다. 그 결과 첫 번째 방법으로 해결하기로 결심했다.
이 고민의 핵심은 결국 '중복 데이터가 적재된다'라는 문제를 어디 수준에서 막아주는걸까? 를 고민하게 되는 문제이다.
만약, 애플리케이션에서 하고 DB는 프리하다면(2번째 방법) DB에서는 값이 중복 적재 될 수 있다는 방법이 열려 있는 상태인 것이고 때문에 어떠한 오류로 중복으로 적재된다면, 결국 적재된 걸 조회할 때 하나만 요하는데 두개가 나오는 등 별도 처리 로직이 필요할 수도 있다. 또한 유니크 제약 조건을 걸어 비록, 비즈니스 로직 상에서 별도의 에외를 처리하는 과정은 필요하지만 'DB 수준에서는 중복이 되지 않는다'가 보장되며 나의 의문과 달리 오히려 DB 유니크 에러 캐치하는 로직을 비즈니스의 로직에서 처리하는게 자연스럽다는 조언도 받았다. '중복 적재를 막는다' 라는 것 자체가 비즈니스 요구사항과 관련된 예외이며 해당 예외가 터졌을 때, 상태코드로 409를 내려줄지, 멱등성을 보장하기 위해 그냥 200 으로 줄 지 등, 예외를 상위 로직에서 요구사항에 맞게 처리할 수 있기 때문이다.

이러한 이유로 나는 DB단에서 유니크 제약조건을 걸어서 애초에 중복 삽입을 방지하고 발생하는 체크 예외를 비즈니스 요구사항에 맞게 처리하도록 설계하는 첫번째 방법을 통해 해결하기로 결정했다.

0개의 댓글

관련 채용 정보