얼마 전에 친구와 대화를 하다가 참조 무결성에 대한 이야기가 나왔는데,
개념을 어렴풋하게만 알고 있어 정리해볼 필요를 느꼈다.
이 글은 아래 내용에 대해 다룬다.
- 데이터 무결성이란 무엇인가?
- 데이터 무결성의 종류
- 데이터 무결성의 주요 요소와 예시
물론 정보통신기술용어해설에서 지적하듯, 데이터 무결성은 정보보호 분야나 전자회로 분야에서도 쓰이는 만큼 본문 이상의 의미를 내포하고 있다.
여기에서는 데이터 무결성의 의미를 관계형 데이터베이스의 경우로 한정짓는다.
데이터 무결성
데이터 무결성(Data Integrity)이란 무엇일까?
한국데이터산업진흥원에서는 데이터 무결성에 대해, 아래와 같이 정리하고 있다.
데이터베이스에서 무결성은 무엇으로부터의 무결성일까? 개발 환경일까, 데이터베이스 자체일까? 정답부터 말하면 ‘구축하고자 하는 비즈니스의 의미’라고 할 수 있다. 우리가 구축하고자 하는 대상 데이터베이스는 업무에서 발생하는 데이터를 저장, 검색, 수정하는 용도로 사용된다. 즉 비즈니스로부터 데이터가 입력되고 또 이용된다는 것이다.
일반적으로 트랜잭션(transaction)은 ‘업무적으로 의미 있는 논리적인 일의 처리 단위’라고 정의된다. 이것을 영어로 표현하면 ‘A Logical Unit of Work’가 된다. 여기서 논리적인 일의 처리 단위는 실제로 트랜잭션이 처리될 때 구분되는 단위와는 다르다. 즉 각각의 SQL 문장과는 다른 비즈니스를 처리하기 위한 단위로 하나의 트랜잭션이 정의된다.
데이터 무결성은 이런 트랜잭션을 유지시켜주는 최소한의 장치를 엔티티타입과 관계 그리고 속성 등에 걸어주고 그것을 유지할 수 있게 해주는 것을 의미한다. 실전 프로젝트 현장에 가보면 데이터베이스 성능을 중요하게 생각하는 곳부터 데이터 무결성은 전혀 안중에 두지 않고 곧바로 데이터베이스 성능을 향상시키기 위해 무분별한 반정규화나 중복, FK Contranit와 컬럼 제약 조건의 생략 등을 저지른다.
이 경우 당장 프로젝트를 오픈할 때는 별 문제가 없어 보인다. 그러나 데이터베이스가 장기적으로 유지되고 지속적으로 데이터베이스에 입력, 수정, 삭제 등의 트랜잭션이 발생하면 제약조건이 걸리지 않은 데이터는 자연스레 업무적으로 무의미하거나 논리적으로 맞지 않는 데이터베이스에 위치하게 된다. 이것이 데이터 무결성을 깨는 요소라고 볼 수 있다.
데이터 무결성이 깨지는 것은 시간에 따라 점진적으로 증가하는 특징을 가지고 있다. 마치 오랜 시간동안 지속적으로 바위 위에 떨어지는 낙숫물이 결국 바위를 깨뜨리고 퇴적작용을 유발해 지각 변동을 야기하는 것과 같다.
출처: 아는 만큼 보이는 데이터베이스, 데이터 무결성의 실무적용(링크)
너무 명확한 글이라 이것만으로도 설명이 된다고 생각한다.
그래도 조금 더 정리해보자.
데이터 무결성은, 데이터베이스에 저장된 데이터 값과 그것이 표현하는 현실의 비즈니스 모델의 값이 일치하는 정확성을 의미한다고 할 수 있다.
데이터 무결성의 종류
데이터 무결성에는 여러 종류가 있다.
우선 정보처리기사 학습 자료와 한국데이터산업진흥원의 자료를 바탕으로 정리해 보았다.
종류 | 내용 |
개체 무결성 | 기본 테이블의 기본키를 구성하는 어떤 속성도 NULL 값이나 중복값을 가질 수 없다. |
참조 무결성 | 외래키 값은 NULL이거나 참조 릴레이션의 기본키 값과 동일해야 한다. 즉, 릴레이션은 참조할 수 없는 외래키 값을 가져서는 안된다. |
도메인 무결성 | 주어진 속성 값이 정의된 도메인에 속한 값이어야 한다. |
사용자 정의 무결성 | 속성 값들이 사용자가 정의한 제약조건에 만족되어야 한다. |
NULL 무결성 | 릴레이션의 특정 속성 값이 NULL이 되어서는 안된다. |
고유 무결성 | 릴레이션의 특정 속성에 대해, 각 튜플이 가지는 속성값들이 서로 달라야 한다. |
키 무결성 | 하나의 릴레이션에는 적어도 하나의 키가 존재해야 한다. |
관계 무결성 | 릴레이션의 어느 한 튜플의 삽입 가능 여부 또는 한 릴레이션과 다른 릴레이션의 튜플들 사이의 관계에 대한 적절성 여부를 준수해야 한다. |
데이터 무결성의 주요 요소와 예시
위에서 정리한 데이터 무결성 중, 특히 중요한 몇 가지를 정리하여 예시와 함께 적어본다.
개체 무결성
테이블의 기본키는 NULL이나 중복값이 들어갈 수 없다.
만약 아래와 같은 상황이 발생하면 어떨까?
- 대학교의 수업 수강자 정보를 저장한 테이블이 있고, 학생의 학번을 기본키로 사용한다.
- 그런데, 외국에서 온 교환학생 일부의 학번 정보가 적절하게 저장되지 못해 학번 속성에 Null이 들어갔다.
- 또한 일부 교환학생은 이전 학교에서 쓰던 학번을 저장했는데, 이 학번이 본교 재학생 학번과 중복된다.
테이블 예시는 아래와 같다.
학번(기본키) | 이름 | 이메일 |
12345678 | 김재학 | abc@gmail.com |
<Null> | John Doe | def@naver.com |
12345678 | 박교환 | xyz@daum.net |
이때 김재학씨나 John Doe씨의 정보를 검색하려고 하면 문제가 발생한다.
- 김재학씨와 박교환씨의 학번이 같으므로, 둘 중 어느 것을 검색하려고 하는지 알 수 없다.
- John Doe의 학번이 Null이므로, 적절하게 검색을 수행할 수 없다.
그렇기 때문에, 이러한 문제를 미연에 방지하고자 개체 무결성을 지켜야 한다.
개체 무결성은 PK(Primary Key, 기본 키) 제약 조건에 의해 준수된다.
- 학번이나 이메일, 혹은 이름을 기본 키로 쓰면 개체 무결성을 준수하지 못할 수 있다.
그래서 기본 키에 대해서는 키 생성 전략을 이용하기도 한다. - 예를 들어 JPA에서는 기본키 자동 생성 전략을 제공하여, 기본 키 속성에 자동으로 증가하는 값이나 DB의 전략을 따르는 특수 값 등을 사용하도록 지원한다.
참조 무결성
외래키 값은 NULL이거나 참조 릴레이션의 기본키 값과 동일해야 한다.
예를 들어, 주문 테이블에서 어떤 고객이 주문했는지 참조하기 위해 외래키로 고객의 이름 정보를 보유한다고 하자.
주문번호(기본키) | 고객의 이름(외래키) | 주문 금액 |
1 | 홍길동 | 10,000 |
2 | 김덕배 | 20,000 |
이때 만약 고객 테이블에 홍길동이 2명이라면 어떨까?
해당 주문을 수행한 엔티티를 고객 테이블에서 찾을 수 없게 된다.
그렇기 때문에, 관계형 데이터베이스에서 외래키를 지정할 때는 중복을 방지하기 위해, 기본키 값을 사용하도록 한다.
혹은, 특수한 상황(테이블에서 참조를 선택적으로 수행하는 경우)에 한해 외래키를 NULL로 지정하도록 한다.
그렇기 때문에, 참조 무결성은 FK(Foreign Key, 외래키) 제약에 의해 준수된다.
도메인 무결성
주어진 속성 값이 정의된 도메인에 속한 값이어야 한다.
또 예를 들어보자. 만약 고객 테이블이 아래처럼 구성되어 있다.
고객 ID(기본키) | 이름 | 이메일 | 내국인 여부 |
1 | 홍길동 | abc@gmail.com | FALSE |
위의 테이블의 속성 중 내국인 여부 속성을 보자. 이 값에는 논리적으로 TRUE, FALSE 두 값만 들어갈 수 있다.
그런데 만약, 해당 속성의 타입을 문자열로 지정했다면 어떨까?
사용자가 내국인 여부에 "내국인", "맞음", "O", "TRUE" 등의 값을 섞어서 삽입하면 분류할 수 있을까?
그렇기 때문에, 도메인 무결성은 속성에 대한 타입과 제약을 부여하여 준수한다.
- 해당 속성 값의 타입(문자열, 정수, Boolean 등)
- 해당 속성 값의 범위(예를 들어, 나이는 음수가 될 수 없음)
- 해당 속성 값의 길이(이름 데이터는 법적인 길이 제한을 넘지 않음)
- 해당 속성 값의 NULL 허용 여부(이름이나 이메일에 NULL이 들어갈 수 없음)
마치며
이 글을 쓰기 위해 몇몇 레퍼런스를 참고했고, 확신이 없어 이전에 공부했던 정보처리기사 책까지 꺼내왔다.
그 중 유용했던 레퍼런스를 정리했다.
- 위키피디아의 데이터 무결성 문서: 링크
- 정보통신기술용어해설의 무결성 제약조건 문서: 링크
- 한국데이터산업진흥원의 아는 만큼 보이는 데이터베이스, 데이터 무결성의 실무적용 문서: 링크
글을 적으면서 데이터베이스에 대한 지식이 부족함을 많이 느꼈다.
이런 기본적인 내용이라도, 조금씩 정리하며 배워가고자 한다.
잘못된 내용이 있다면 댓글 부탁드립니다.
'프로그래밍 > JPA, Database' 카테고리의 다른 글
[JPA] 비관적 락과 낙관적 락, 트랜잭션의 격리 수준 (1) | 2021.10.15 |
---|---|
DB 커넥션 풀과 HikariCP (0) | 2021.10.14 |
H2로 SpringBoot 테스트 도중 SQL이 실행되지 않는 경우 대응법 (0) | 2021.10.08 |
[JPA] findAll, findAllBy, findAllByIn AOP로 성능 테스트해보기 (6) | 2021.09.02 |
[JPA] Bean Validation과 Hibernate apply-to-ddl (1) | 2021.02.22 |
댓글