데이터 모델링의 중요성
데이터 모델링은 필요한 데이터 항목을 나열하고 테이블 설계를 하는 작업이다. 애플리케이션을 만들 때 가장 중요한 것은 '어떤 데이터 항목이 필요한가'이다. 항목이 부족하면 나중에 추가할 수 있지만 이것은 대부분의 경우 애플리케이션의 개선이 필요하고 가동 후에 실시하는 것이기 때문에 쉽지 않다. 어떤 항목이 필요한지를 결정하는데에는 '데이터를 어떻게 사용하는지'에 대한 '업무 요구사항'이 명확하게 되어 있어야 한다. 물론, 기능 추가가 자주 발생하는 애플리케이션에서 데이터 항목을 미리 완벽하게 추론해는 것은 불가능하다. 그렇기에 나중에도 데이터를 쉽게 추가 및 변경할 수 있도록 설계하는것이 중요하다.
요구사항
- 직원은 고유의 사원 번호를 가진다.
- 같은 이름의 사원이 있는 경우가 있다.
- 이름의 한자가 다르다 해도 발음이 같은 직원이 있는 경우가 있다.
- 직원은 메일 주소가 부여된다. 메일 주소는 중복되지 않는다.
- 경력 사원 등 수속 절차에 따라 메일 주소의 부여가 지연될 수 있으며, 이 경우는 당분간 메일 주소가 없는 상태가 된다.
- 직원은 어느 부서인가에 반드시 소속된다.
- 부서 이름이 중복될 수 없다.
- 부서 전화번호는 중복될 수 없다.
테이블 관계 도입
요구사항
- 직원은 고유의 사원 번호를 가진다.
- 같은 이름의 사원이 있는 경우가 있다.
- 이름의 한자가 다르다 해도 발음이 같은 직원이 있는 경우가 있다.
- 직원은 메일 주소가 부여된다. 메일 주소는 중복되지 않는다.
- 경력 사원 등 수속 절차에 따라 메일 주소의 부여가 지연될 수 있으며, 이 경우는 당분간 메일 주소가 없는 상태가 된다.
- 직원은 어느 부서인가에 반드시 소속된다.
- 부서 이름이 중복될 수 없다.
- 부서 전화번호는 중복될 수 없다.
사원을 관리하고 싶으면, 테이블을 만들어서 관리해보자.
이렇게 하나의 테이블에 모든 데이터를 저장해서 관리하는 것은 비효율 적이다. 왜냐하면 중복되는 데이터가 너무 많기 때문이다. 중복된 데이터를 계속 입력하다보면, 부서 전화번호의 숫자를 틀릴 가능성이 높다. 그러면 데이터의 무결성이 깨진다. 하나의 테이블 보다는 나누는게 좋다.
그러면 직원은 직원, 부서는 부서로 별도의 테이블로 관리해보자.
테이블을 서로 분리하여, 전화번호를 중복해서 등록하지 않아도 되도록 했다. 테이블의 key 값은 쉽게 바뀔 수 있는 것 보다 바뀌기 어려운 것으로 지정해야한다. 테이블을 나눠놓으니깐, 부서 번호가 동일하면, 부서 이름과 부서 전화번호도 동일한 것이 보장된다. 따라서, 입력 실수 가능성이 크게 줄어든다.
📌 참조 무결성 제약
무결성은 데이터가 정확하고 일관되게 유지되는 상태를 의미한다. 테이블을 2개로 나누었을 때 생기는 장점이 또 있다. 인사과 사원 정보를 등록할 때, 부서 번호를 100번이 아니라 테이블에 없는 값인 1000번으로 잘못 등록하지 못하도록 DB에서 막아준다. 이것이 참조 무결성 제약이다. 데이터의 정확성과 일관성을 유지해준다. 데이터베이스는 참조 무결성 제약을 통해 사원 테이블에 부서 테이블에 없는 정보를 입력할 경우 오류를 반환해준다.
데이터베이스는 참조 무결성 제약을 통해 해당하는 외래키가 존재하는 값인지 아닌지에 대해서 검증을 한다. 이 때 검증 속도는 고속으로 처리해야한다. 그렇기 때문에 외래키는 인덱스가 필수다. 모든 RDBMS가 외래 키에는 인덱스를 부여하고 있다.
참조 무결성 제약이 모든 것을 해결해줄 수 있는 것은 아니다. 예를 들어서 인사과 사원 정보를 등록할 때, 부서 번호를 100번이 아닌 경리부인 101번으로 적을 경우 데이터베이스에 이미 존재하는 값이므로 데이터베이스에서 이것을 오류라고 인식할 방법이 없다. 이미 존재하는 값에 대한 입력 실수를 방지하려면 애플리케이션에서 유효성 검증 로직으로 에러를 잡아야한다.
테이블 설계의 타당성 검증
한 명의 사원이 여러 부서를 겸직할 수 있다고 해보자. 그런 경우 어떻게 해야할까?
이런식으로 사원 정보 테이블에 '부서 번호1', '부서 번호2' 이렇게 적는것이 맞는 것일까? 만약에 A 사원이 소속된 부서의 개수가 100개 인 경우 어떻할까? 위와 같은 방식으로 한다면 사원 정보 테이블의 크기가 엄청 커지고, 겸직을 하지 않는 사원들한테는 부서 번호2, 부서 번호3, 부서 번호4, ... 여러 부서 번호들이 다 NULL 값으로 들어가게 된다. 물리적인 공간을 낭비하고 있는 것이다.
이처럼 부서 번호를 set 집합형으로 사용하여 사용하면 된지 않나 라는 생각을 할 수 있다. 그러나 집합을 지원해주지 않는 데이터베이스도 있고, 집합형을 사용했을 때, 검색 조건인 인덱스로 사용하기 어렵기 때문에 도입이 쉽지 않다. 참고로 DB에서는 집합형을 권장하지 않는다.
지금 다니고 있는 회사에서도 이런 경우가 발생할뻔한 적이 있다. 예를 들어서 '쿠릉 초코칩' 이라는 과자가 있다고 할 떄, 소비자들이 해당 과자를 어떤 방식으로 결제를 했는지 알려줘야한다. 결제 방식으로는 카드, 현금, 계좌이체, 무통장 입금 등이 있다. 단, 마감 처리가 된 데이터는 조회할 수 없다. 카드 결제 방식 내역들의 데이터가 마감이 된 경우 카드 결제 방식 내역들은 조회할 수 없지만, 마감이 안된 현금, 계좌이체, 등 다양한 방식으로 결제한 내역은 조회할 수 있다.
이런 경우에 '쿠릉 초코칩' 테이블 열에 '카드 방식 마감 유무', '현금 방식 마감 유무', ... 등등 다양한 결제 방식을 통한 마감 유무를 체크하는 값을 추가하려고 했다. 하지만 이것은 메모리 낭비가 심하기 때문에, 그렇게 안하고 마감 테이블을 따로 만들어서 분리를 했다.
'[DB] > DB' 카테고리의 다른 글
[DB] 인덱스를 활용한 데이터의 빠른 접근 속도 (0) | 2022.11.02 |
---|---|
[DB] DB의 필요성 (0) | 2022.11.02 |
[DB] 스프링 부트의 다양한 DB 연동 방법 (0) | 2022.03.31 |