403. 삭제 이상 (Deletion Anomaly)

⚠️ 이 문서는 데이터베이스 테이블 설계를 잘못했을 때, **하나의 데이터를 지우려고(DELETE) 했는데 그 데이터와 같은 줄에 묶여있던 '절대 지워지면 안 되는 전혀 다른 소중한 데이터'까지 원치 않게 함께 날아가는 끔찍한 부작용인 '삭제 이상'**을 다룹니다.

핵심 인사이트 (3줄 요약)

  1. 본질: 정규화를 하지 않아 여러 주제의 데이터(학생 정보 + 과목 정보)가 한 테이블에 묶여 있을 때, 한 주제의 데이터(학생)를 지우면 다른 주제의 데이터(과목)도 같이 사라지는 연쇄 삭제 현상이다.
  2. 원인: 여러 정보가 하나의 행(Row/Tuple) 안에 끈적하게 결합되어 있기 때문이다. (관계의 종속성)
  3. 해결책: 삭제 이상을 일으키는 억지스러운 속성들을 떼어내서 **새로운 테이블로 분리(정규화)**하면 깔끔하게 해결된다.

Ⅰ. 개요: 벼룩 잡으려다 초가삼간 태운다 (Context & Necessity)

"박민수 학생이 우리 학교를 자퇴했어. DB에서 지워!"

초보 개발자가 만든 수강_테이블(학번, 이름, 과목코드, 과목명)이 있다.

  • 박민수 학생의 자퇴를 처리하기 위해 DELETE 쿼리를 날려본다.
  • DELETE FROM 수강 WHERE 학번 = '1003';

대참사 발생: 박민수는 우리 학교에서 **'AI 개론'**이라는 과목을 듣는 유일한 학생이었다. 박민수의 데이터(행)가 지워지면서, 그 옆에 붙어있던 '과목코드: AI101', '과목명: AI 개론' 이라는 과목의 기본 정보까지 통째로 날아가 버렸다. 이제 이 학교의 DB에는 'AI 개론'이라는 과목 자체가 아예 존재하지 않는 상태가 되어버렸다. 이것이 바로 **삭제 이상(Deletion Anomaly)**이다.

📢 섹션 요약 비유: 삭제 이상은 **'도서관 대출 장부'**와 같습니다. 장부에 [빌린 사람, 책 이름]을 한 줄에 묶어서 적어놨죠. 만약 어떤 사람이 도서관을 탈퇴해서 그 사람의 이름을 지웠는데, 그 사람이 빌렸던 책이 도서관에 딱 한 권 있는 희귀한 책이었다면? 장부에서 그 책의 이름조차 영원히 지워져 버리는 황당한 상황입니다.


Ⅱ. 삭제 이상이 발생하는 구체적 사례 ★

시험에 가장 자주 나오는 사례를 테이블로 분석해 보자.

학번 (PK)과목코드 (PK)성적과목명
1001CS101A컴퓨터
1002CS101B컴퓨터
1003MA101A수 학

(기본 키는 학번 + 과목코드)

위 테이블에서 1003번 학생이 'MA101(수학)' 수강을 취소했다.

  • 이 학생의 기록을 지우기 위해 마지막 행을 통째로 날린다.
  • 결과: 학생(1003)이 사라지는 건 맞는데, 그 과정에서 **'MA101 과목의 이름이 수학'**이라는 학교의 소중한 기준 정보(Master Data)까지 허공으로 날아가 버린다.

Ⅲ. 해결책: 정규화를 통한 테이블 분리

삭제 이상이 생기는 근본적인 이유는 **'학생이 수강하는 사실'**과 **'과목 자체에 대한 사실'**이라는 두 개의 완전히 다른 주제가 하나의 테이블에 섞여 있기 때문이다.

문제를 일으킨 부분(과목 정보)을 도려내서 새로운 테이블로 분리한다. (제2정규형 적용 - 397번 문서)

  1. 수강_테이블 [학번, 과목코드, 성적]
  2. 과목_테이블 [과목코드, 과목명]

이제 1003번 학생이 수강을 취소하면 어떻게 될까? 1번 수강_테이블에서 1003번 줄만 쏙 지우면 끝이다. 2번 과목_테이블에는 'MA101 - 수학' 이라는 정보가 안전하게 살아있다! 완벽하게 해결되었다.

┌──────────────────────────────────────────────────────────────┐
│           삭제 이상(Deletion Anomaly) 발생 구조 시각화               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ [ ❌ 정규화 전 (하나의 테이블) ]                                     │
│  [ 학번 | 과목코드 | 성적 | 과목명 ]                                │
│   1003     MA101     A     수학    ◀── Delete!                 │
│                                (학생을 지웠는데 과목 정보까지 소멸 💥)│
│                                                              │
│ [ 🟢 정규화 후 (테이블 분리) ]                                      │
│  1. 수강: [ 학번 | 과목코드 | 성적 ]                                 │
│            1003     MA101    A     ◀── Delete!                 │
│                                                              │
│  2. 과목: [ 과목코드 | 과목명 ]                                      │
│            MA101     수학          ◀── (과목 정보는 안전하게 보존 🛡️) │
└──────────────────────────────────────────────────────────────┘

Ⅳ. 결론

"데이터의 손실은 시스템의 가장 큰 죄악이다." 데이터베이스를 설계할 때 삭제 이상을 방치하면, 엉뚱한 기준 데이터(Master Data)가 날아가서 시스템 전체에 'NullPointException'이 폭발하게 된다. 학생 정보는 지워져도, 학교의 과목 정보는 영원히 남아있어야 한다. 삭제 이상은 프로그래머가 실수로 잘못 지운 것이 아니라, 애초에 테이블 구조(스키마)가 하나를 지우면 다른 것도 지워질 수밖에 없게 잘못 설계되었기 때문에 발생하는 구조적 질병이다.


📌 관련 개념 맵

  • 관련 이론: 3대 이상 현상 (Anomaly) - 삽입 이상, 삭제 이상, 갱신 이상
  • 해결 기술: 정규화 (Normalization)
  • 대칭 현상: 삽입 이상 (Insertion Anomaly - 402번 문서)
  • 비슷한 장애 (물리적): Cascade Delete (외래 키 옵션으로 연쇄 삭제되는 현상 - 의도적인 설정이라는 점에서 다름)

👶 어린이를 위한 3줄 비유 설명

  1. 서랍장 한 칸에 내 '장난감'이랑 엄마의 '비상금'을 같이 묶어서 넣어뒀어요. (정규화 안 된 테이블)
  2. 내가 장난감이 싫어져서 쓰레기통에 확 버렸는데, 아뿔싸! 엄마의 비상금까지 같이 버려진 거예요. (삭제 이상)
  3. 장난감은 장난감 서랍에, 비상금은 금고(다른 테이블)에 따로 보관했어야 이런 슬픈 일이 안 생기겠죠?