[데이터베이스/DB] 키(Key)의 종류와 개념

kindof

·

2021. 9. 26. 18:05

1-1. 들어가면서

데이터베이스는 수 많은 테이블과 그 안의 데이터들로 구성되어 있습니다. 그리고 그 테이블은 정렬되지 않고 조직화되지 않은 수천 개, 수만 개의 레코드로 확장되어 있습니다.

 

이러한 테이블 속에서 특정 레코드를 가져오려면 그 레코드를 유일하게 식별할 수 있는 조건으로 조회하는 작업이 필요한데요. 이 때 필요한 개념이 데이터베이스에서 키(Key)이며, 이번 시간에는 여러가지 키에 대한 개념에 대해 정리해보겠습니다.

 

우선 키의 정의는 아래와 같습니다.

 

키(Key): 관계형 데이터베이스(RDBMS)에서 테이블 관의 관계를 설정 및 식별하고, 테이블 내부의 레코드를 고유하게 식별하는 데 사용할 때 사용하는 속성

 

그리고 밑에서 강한 엔티티 타입과 약한 엔티티 타입을 설명하면서 부분키(Partial Key)에 대한 설명도 하려고 하는데요. 이 부분을 위해 우선 '엔티티란 무엇인지'에 대해 정의하고 시작하겠습니다.

 

 

1-2. 엔티티(Entity)?

엔티티(Entity)는 사람, 장소, 물건 등 독립적으로 존재하면서 고유하게 식별가능한 객체를 의미합니다. 

 

학교에 가면 건물, 학생, 교수님, 수업, 조교님 등이 있는데 이 모든 것들이 하나의 Entity겠죠.

 

그런데 Entity와 관련해서 조금 헷갈리지만 반드시 구분해서 사용해야 할 개념들이 있는데요. 바로 Entity Type, Entity Set, 그리고 Entity입니다. 그림을 통해 차이점을 들여다보겠습니다. 

 

엔티티, 엔티티 집합, 엔티티 타입

Entity Type(엔티티 타입)이란 ER모델에서 스키마(Schema)에 해당합니다. 동일한 속성을 갖게 되는 Entity를 정의해주는 인터페이스라고 할 수 있죠.

 

Entity Set(엔티티 집합)은 동일한 속성을 갖는 실제 Entity들의 집합인데요. 각각의 Entity는 Entity Set에 속하게 되고 Entity Type에 종속됩니다.

 


 

그럼 이제 본격적으로 여러 가지 키(Key)의 종류와 개념에 대해 살펴보겠습니다.

 

 

2. 슈퍼키(Super Key)

슈퍼키는 각 튜플을 유일하게 식별할 수 있는 속성들의 집합입니다.

 

슈퍼키는 유일성만 만족하면 되는 키이기 때문에 모든 속성들을 그 자체로 하나로 묶은 것도 슈퍼키라고 볼 수 있으며, 굳이 필요하지 않은 속성도 끼워 넣어도 유일성만 만족하면 슈퍼키라고 할 수 있습니다.

 

 

 

3. 후보키(Candidate Key)

후보키는 슈퍼키 중에서 유일성과 최소성을 만족하는 키로써, 이름 그대로 기본키가 될 수 있는 '후보' 키입니다.

 

이 때, 어떤 테이블에서 유일성과 최소성을 만족하는 키는 여러 개가 존재할 수 있는데요. 아래와 같은 테이블을 보겠습니다.

 

학번 주민번호 이름 나이
2016123456 960918-1111111 A 21
2017000123 980909-2222222 B 21
2020151321 990208-3333333 C 22
20210241231 000308-4444444 D 20

위 테이블에서 '학번'과 '주민번호'는 속성 하나로 모든 튜플을 구분할 수 있는 후보키가 됩니다. 그런데 '이름+나이'는 두 개의 속성으로 모든 튜플을 구분할 수 있기 때문에 최소성을 만족한다고 볼 수 없고, 후보키라고 말할 수 없습니다.

 

 

 

4. 기본키(Primary Key)

기본키는 후보키 중에서 특별히 선정된 키로 중복된 값을 가질 수 없으며, 후보키의 성질을 갖습니다. 즉, 기본키는 유일성과 최소성을 가지며 튜플을 식별하기 위해 반드시 필요한 키입니다.

 

기본키는 NULL 값을 가질 수 없기 때문에 튜플에서 기본키로 설정된 속성에 NULL값을 지정할 수 없으며, 혹시라도 이후에 NULL 값이 들어갈 수 있는 속성에 대해서는 기본키로 지정해서는 안 됩니다. 기본키가 NULL 값인 튜플은 다른 튜플들과 구별하여 접근하기 어렵기 때문에 이런 가능성이 있는 키는 기본키로써의 역할을 제대로 할 수 없기 때문이죠.

 

또한, 값이 자주 변경될 수 있는 속성이 포함된 후보키는 기본키로 부적합합니다. 이유는 크게 두 가지가 있다고 생각하는데요.

  • 기본키에 대한 인덱스(INDEX)가 걸려있을 때, 값을 업데이트하면 인덱스에 따라 재정렬해야 하기 때문에 비효율적일 수 있다.
  • 해당 기본키를 다른 테이블에서 참조하는 경우 자식 테이블의 데이터를 처리하는 데 정합성이 깨질 수 있다.

따라서 기본키로 지정하는 속성을 고려할 때, 그 값이 자주 바뀔 수 있다면 절대 기본키로 설정하여서는 안 됩니다.

 

 

 

5. 대체키(Alternate Key)

대체키는 후보키가 둘 이상인 상황일 때, 기본키로 선택받지 못한 나머지 후보키를 말합니다. 

 

 

6. 외래키(Foreign Key)

테이블은 정규화를 통해서 다른 테이블과 관계를 맺게 되고, 이 때 다른 테이블의 데이터를 참조할 때 없는 값을 참조할 수 없도록 제약을 주는 키를 말합니다. 그리고 이를 반대로 생각하면, 외래키는 다른 테이블의 기본키와의 매핑을 통해 테이블 간 참조를 가능하게 하고 필요 시 조인해서 결과를 보여줄 수 있는 역할을 하게 됩니다.

 

가장 일반적인 예로 일대다(OneToMany) 관계를 맺는 엔티티를 테이블로 설계할 때, 일(One)쪽에 기본키를 설정하고 다(Many)쪽에 외래키를 일(One) 쪽의 기본키로 설정하여 연관관계를 지정하는 상황을 떠올릴 수 있죠. 

 

이렇게 하면 참조되는 부모 테이블을 먼저 생성한 뒤 데이터를 넣고 참조하는 자식 테이블에 데이터를 삽입해야 하는 제약이 생기며 부모 테이블이 삭제될 때 자식 테이블이 참조할 수 있는 기본키가 삭제된다면 이를 방지하는 제약도 생기게 됩니다. 물론 CASCADE 속성을 이용하여 이런 제약을 자동으로 처리하도록 할 수 있습니다.

 

또한, 테이블은 여러 테이블과 관계를 맺을 수 있기 때문에 외래키를 가진 테이블 입장에서는 참조하는 테이블이 여러 개라면 여러 개의 외래키를 가질 수 있게 됩니다. 

 

7. 강한 엔티티 타입과 약한 엔티티 타입, 그리고 부분키(Partial Key)

위에서 말씀드렸던 것처럼 Entity 타입은 Entity의 속성을 결정해주는 스키마 역할을 합니다.

 

그렇다면, 강한 엔티티 타입과 약한 엔티티 타입이라고 나누는 것은 해당 타입에 속하는 엔티티들의 속성이 무언가 다르다는 것이겠죠? 

 

먼저 강한 엔티티 타입(Strong Entity Type)은 자신의 키 속성만을 이용해서 고유하게 엔티티들을 식별할 수 있는 타입을 말합니다. 독립적으로 존재할 수 있는 엔티티 타입이죠.

 

하지만 약한 엔티티 타입(Weak Entity Type)은 자신의 키 속성만으로는 엔티티를 고유하게 식별할 수 없는 타입을 말합니다. 따라서 강한 엔티티 타입의 키 속성과 자신이 가진 키 속성을 동시에 사용해서 자신의 엔티티들을 식별해낼 수 있게 설계된 타입입니다.

 

그리고 이 때 부분키(Partial Key)란 "강한 엔티티 타입의 키와 결합해서 쓰일 때 자신의 엔티티를 고유하게 식별해주는 약한 엔티티 타입이 가진 키"라고 정의합니다. *강한 엔티티 타입에서는 어차피 스스로 엔티티를 판별할 수 있으니까 별다른 네이밍을 안 해도 되겠죠?

 

지금까지 설명한 내용을 그림으로 보면 아래와 같습니다.

강한 엔티티 타입과 약한 엔티티 타입

"직원(EMPLOYEE)"과 "가족(DEPENDENT)"라는 엔티티 타입이 존재하고, 직원 엔티티 타입에는 사원번호와 이름이라는 속성이 존재합니다. 그리고 약한 엔티티 타입인 가족에는 가족의 이름과 성별이 존재하죠. 회사의 복지를 위한 서비스 개발을 한다고 하면 위와 같은 모델이 충분히 만들어질 수 있겠죠?

 

자, 그러면 위와 같은 상황에서 가족이라는 엔티티 타입에서 (조성현, 남자)라는 엔티티를 정의해봅시다. 이 때, (조성현, 남자)라는 Entity는 (1, A)의 가족입니다. 그런데 만약 (조성현, 남자)라는 사람이 또 존재하고, 이 사람은 (2, B)의 가족이라고 해볼까요?

 

그러면 이름과 성별만으로는 두 명의 (조성현, 남자) 사람 중에서 누가 어떤 사람의 가족인지 알 수 없습니다. 따라서 이 때 사원번호 속성과 연결을 지어서 "사원번호가 1인 사람의 가족인 조성현"이라는 방식으로 엔티티를 식별해야만 하죠. 이해가 되셨나요?

 

🧐 왜 나누지?

그렇다면 강한 엔티티 타입과 약한 엔티티 타입은 왜 나눌까요?

 

이전에 제가 썼던 정규화에 대한 글을 읽어보셨거나 정규화에 대한 이해가 있으신 분이라면 충분히 아실 것 같은데요. 어떻게 보면 강한 엔티티 타입과 약한 엔티티 타입은 분리를 하려고 한 게 아니라, 분리가 된 겁니다.

 

즉, 정규화를 통해 릴레이션을 쪼개다보니 위와 같은 스키마 형태가 생기게 되었고 이를 정의한 것이 강한 엔티티 타입과 약한 엔티티 타입인 것이죠. 독자적인 개념에서 파생된 것이 아니라는 뜻입니다.

 

만약 위에서 설명한 예제의 EMPLOYEE와 DEPENDENT의 속성들을 하나의 릴레이션 안에 정의하게 된다면 어떨까요? 가족이 없는 EMPLOYEE를 삽입한다고 하면 필요없는 DEPENDENT의 속성들이 NULL로 정의되면서 삽입이상이 발생하지 않을까요?🧐

 


8. 나가면서

키(Key)에 대한 개념은 그 자체로 정의가 중요한 부분입니다. 각 키가 어떤 제약을 만족해야 하며, 어떤 상황에서 쓰이는 것을 알아야 실제 개발을 할 때 적절한 연관관계 매핑을 할 수 있죠.

 

어떻게 보면 사소한 내용이지만 각 키가 어떤 개념이며 왜 필요한지에 대해 생각해보면 좋을 것 같습니다.

 

감사합니다.