식별자, 주식별자 조건과 분류 기준 정리
엔터티나 속성은 그래도 감이 오는데, 식별자로 들어가는 순간 주식별자, 보조식별자, 후보식별자, 본질식별자, 인조식별자, 내부식별자, 외부식별자가 한꺼번에 쏟아진다. 이름이 일곱 개쯤 되니까 '외울 게 많다'고 느끼고, 외울 게 많다고 느끼면 대충 넘길 수 있다.
그런데 이건 개념이 어려운 게 아니라 설명 순서가 뒤엉킨 탓이다. 보통은 일곱 개 이름을 한 줄로 늘어놓고 각각 뜻을 붙여 준다. 그러면 이름끼리 어떤 관계인지가 안 보인다. 주식별자와 본질식별자가 같은 층에 있는 말인지, 서로 반대말인지조차 헷갈린다.
진짜 걸림돌은 이거다. 식별자 용어들은 하나의 목록이 아니라, 서로 다른 질문에 대한 답이다. '대표냐 아니냐'를 묻는 질문의 답과 '어디서 왔냐'를 묻는 질문의 답을 같은 줄에 놓으니까 섞이는 것이다.
이 글을 다 읽고 나면 다음 한 문장으로 판별할 수 있게 된다. 식별자 이름이 나오면 먼저 '이 이름은 어느 질문에 대한 답인가'를 묻는다. 질문을 찾으면 짝이 되는 반대말이 자동으로 따라 나온다.
주식별자가 되려면 관문 네 개를 통과해야 한다
주식별자는 도서관 회원증 번호 같은 것이다. 회원증 번호는 회원 한 사람마다 다르고, 번호 하나만 대면 누구인지 바로 나오고, 한 번 받으면 평생 안 바뀌고, 회원이면 반드시 가지고 있다. 이 네 가지가 모두 성립해야 회원증 번호로 쓸 만하다. 하나라도 어긋나면 그 번호로 대출 기록을 관리할 수 없다.
용어로 돌아오면 이 네 가지를 각각 유일성, 최소성, 불변성, 존재성이라고 부른다. 주식별자란 엔터티 안에서 각 인스턴스를 하나로 특정하기 위해 지정한 속성 또는 속성 집합이고, 그 지정이 정당하려면 네 조건을 모두 만족해야 한다.
위 네 조건을 하나씩 뜯어보자.
유일성은 식별자 값 하나가 인스턴스 하나에 정확히 대응한다는 뜻이다. 같은 값을 가진 행이 둘 이상 있으면 그 값으로는 누구를 가리키는지 알 수 없다. 사원 엔터티에서 사원명을 식별자로 쓰면 동명이인이 생기는 순간 무너진다.
최소성은 식별에 꼭 필요한 속성만 남기라는 뜻이다. 속성을 더 붙이면 유일성은 더 확실해지니까 많을수록 좋다고 생각하기 쉬운데, 시험은 정반대로 본다. 사원번호만으로 이미 유일하다면 여기에 부서를 덧붙인 조합은 유일하긴 해도 최소성을 위반한 것이다. 필요 없는 속성이 하나라도 섞이면 주식별자로 부적절하다.
불변성은 한 번 부여된 값이 바뀌지 않아야 한다는 뜻이다. 식별자 값이 바뀌면 그 값을 참조하던 다른 엔터티의 데이터가 전부 어긋난다. 그래서 자주 바뀌는 속성, 이를테면 부서나 직급 같은 것은 식별자 후보에서 먼저 탈락한다.
존재성은 값이 반드시 있어야 한다는 뜻이다. NULL은 '값이 없다'가 아니라 '값을 알 수 없다'이므로, 식별자 자리에 NULL이 오면 그 행이 누구인지 판정할 수 없다. 그래서 주식별자 속성에는 NULL이 올 수 없다.
시험에 자주 나오는 함정
주식별자 속성의 값은 업무 상황 변화에 따라 변경될 수 있어야 한다.
틀렸다. 정확히 반대다. 주식별자는 불변성을 만족해야 하므로 값이 바뀌면 안 된다. 이 선지가 매력적으로 보이는 이유는 '업무 변화에 유연하게 대응해야 한다'는 문장이 모델링 전반에서는 옳은 말처럼 들리기 때문이다. 유연성이 필요한 쪽은 일반 속성이고, 식별자는 오히려 고정되어 있어야 다른 엔터티가 안심하고 참조할 수 있다.
주식별자를 복합 속성으로 구성할 때는 유일성을 확실히 하기 위해 가능한 한 많은 속성을 포함한다.
틀렸다. 최소성 위반이다. 많이 넣을수록 유일성은 확실해지지만, 그 대가로 인덱스가 커지고 이 식별자를 참조하는 모든 엔터티가 불필요한 속성까지 전부 받아 가야 한다. 복합식별자는 필요한 만큼만, 그 이상은 빼는 것이 원칙이다.
후보는 여럿, 대표는 하나 — 그 나머지가 보조식별자다
반장 선거를 떠올리면 편하다. 후보로 나설 자격을 갖춘 학생이 세 명이라고 하자. 투표로 한 명이 반장이 되고, 나머지 두 명은 반장이 아니게 된다. 그렇다고 나머지 두 명이 후보 자격을 잃은 건 아니다. 자격은 그대로고, 대표로 뽑히지 않았을 뿐이다.
식별자도 똑같다. 유일성과 최소성을 만족해 식별자가 될 자격을 갖춘 속성 또는 속성 집합을 후보식별자라고 한다. 이 후보들 가운데 엔터티를 대표하도록 지정한 하나가 주식별자이고, 지정되지 않은 나머지가 보조식별자다. 보조식별자는 대체키라고도 부른다.
회원 엔터티를 예로 들어 보자. 회원번호, 이메일, 휴대폰번호가 모두 회원마다 서로 다르다면 셋 다 후보식별자가 될 수 있다. 여기서 회원번호를 주식별자로 지정하면 이메일과 휴대폰번호는 보조식별자가 된다. 이메일이 유일하지 않아서 탈락한 게 아니라, 대표로 뽑히지 않았을 뿐이다.
반대로 이름은 후보식별자가 될 수 없다. 같은 이름을 가진 회원이 있을 수 있어 유일성이 깨지기 때문이다. 자격 미달과 낙선은 다른 이야기다.
주식별자를 고를 때는 관례적으로 이런 기준을 본다. 업무에서 자주 이용되는 속성인가, 값이 길거나 복잡하지 않은가, 속성 개수가 너무 많지 않은가. 명칭이나 내역처럼 서술적인 속성은 길이가 길고 변경 가능성도 커서 주식별자로 잘 쓰지 않는다.
시험에 자주 나오는 함정
보조식별자는 유일성을 만족하지 못하므로 인스턴스를 식별할 수 없다.
틀렸다. 보조식별자도 후보식별자였기 때문에 유일성을 만족한다. 식별 자체는 가능하다. 주식별자와 갈리는 지점은 유일성 여부가 아니라 '대표로 지정되었는가'다. 이 선지는 '보조'라는 단어가 주는 인상, 즉 뭔가 부족하다는 느낌을 이용한 것이다.
후보식별자는 엔터티마다 반드시 하나만 존재한다.
틀렸다. 하나만 존재해야 하는 것은 주식별자다. 후보식별자는 조건을 만족하기만 하면 여럿일 수 있다. '하나'라는 숫자가 어느 용어에 붙는지를 정확히 구분해 두어야 이 유형에서 흔들리지 않는다.
식별자 이름들은 네 가지 질문에 대한 답이다
도입부에서 말한 핵심이 여기다. 식별자 용어를 한 줄로 늘어놓지 말고, 네 개의 질문으로 나눠서 각 질문마다 답이 두 개씩 있다고 보면 전체가 한눈에 정리된다.
첫째 질문은 대표성이다. 이 식별자가 엔터티를 대표하는가. 대표하면 주식별자, 대표하지 않으면 보조식별자다. 앞 절에서 다룬 내용이 바로 이 질문이다.
둘째 질문은 스스로 생성한 값인가다. 자기 엔터티 안에서 만들어진 값이면 내부식별자, 다른 엔터티에서 받아온 값이면 외부식별자다. 외부식별자는 관계를 통해 넘어온 값이므로 데이터베이스 구현 단계에서는 외래키 역할을 한다.
셋째 질문은 속성이 몇 개인가다. 속성 하나로 식별하면 단일식별자, 둘 이상을 묶어서 식별하면 복합식별자다.
넷째 질문은 업무에서 유래한 값인가다. 업무 자체가 가지고 있던 값을 그대로 쓰면 본질식별자, 관리 편의를 위해 새로 만들어 붙인 값이면 인조식별자다.
이렇게 나눠 놓으면 한 식별자가 여러 이름을 동시에 가질 수 있다는 점도 자연스럽게 이해된다. 주문 엔터티의 주문번호는 대표성으로는 주식별자, 생성 주체로는 내부식별자, 속성 수로는 단일식별자, 유래로는 주문 업무가 발생시킨 값이므로 본질식별자다. 네 이름이 충돌하는 게 아니라 네 질문에 각각 답한 것뿐이다.
표만 보면 다 아는 것 같은데 막상 문제에서는 안 떠오른다. 판정을 세 번만 해 보자.
첫째, 학생 엔터티의 학번. 학사 업무가 학생에게 부여하는 값이고 학생 엔터티 안에서 만들어지므로 내부식별자다. 속성 하나로 학생이 특정되므로 단일식별자다. 유래로 보면 우리가 관리 편의로 새로 붙인 번호가 아니라 학사 업무 자체가 발생시키는 값이므로 본질식별자다. 그리고 학생 엔터티를 대표하도록 지정했다면 주식별자다.
둘째, 수강 엔터티의 학번. 같은 학번인데 자리가 다르다. 수강 엔터티가 스스로 만든 값이 아니라 학생 엔터티에서 관계를 타고 넘어온 값이므로 외부식별자다. 여기에 과목코드와 학기를 묶어 수강을 식별한다면 그 조합은 복합식별자이면서 주식별자가 된다. 같은 속성명이라도 어느 엔터티에 놓였는지에 따라 내부냐 외부냐가 갈린다는 점이 이 유형의 핵심이다.
셋째, 그 수강 엔터티에 새로 부여한 수강번호. 학번과 과목코드와 학기를 묶은 세 속성짜리 식별자가 길고 다루기 불편하다는 이유로 일련번호를 하나 새로 만들어 주식별자 자리에 앉혔다고 하자. 이 값은 업무가 원래 가지고 있던 값이 아니라 관리 편의로 만들어 낸 값이므로 인조식별자다. 인조식별자를 판별하는 기준은 '누가 부여했는가'가 아니라 '원래 업무에 있던 값을 대체하려고 새로 만들었는가'다. 학번이나 사업자등록번호처럼 기관이 부여하더라도 업무 자체가 그 값을 가지고 돌아간다면 본질식별자로 본다.
세 번 해 보면 규칙이 보인다. 네 질문은 서로 독립적이고, 각각 따로 답하면 된다. 하나의 답이 다른 질문의 답을 강제하지 않는다.
시험에 자주 나오는 함정
외부식별자는 반드시 주식별자로 사용된다.
틀렸다. 외부식별자는 '다른 엔터티에서 온 값'이라는 뜻일 뿐, 주식별자가 될지 일반 속성으로 남을지는 관계 유형이 결정한다. 부모의 주식별자가 자식의 주식별자 자리로 들어가면 식별관계이고, 자식의 일반 속성으로 들어가면 비식별관계다. 외부식별자라는 말 자체는 이 둘 중 어느 쪽인지 알려 주지 않는다.
인조식별자는 본질식별자보다 항상 우수하므로 가능한 한 인조식별자를 사용한다.
틀렸다. 인조식별자는 본질식별자가 너무 길거나, 복합 속성 개수가 많거나, 업무적으로 변경 위험이 있을 때 대안으로 쓰는 것이지 무조건 나은 선택이 아니다. 인조식별자를 남발하면 원래 유일했어야 할 업무 값의 중복이 걸러지지 않아 같은 내용이 여러 번 들어갈 수 있다. '항상', '반드시'가 붙은 선지는 일단 의심하는 게 좋다.
시험 직전에 이것만
기억할 문장 세 개
- 유일성 최소성 불변성 존재성, 넷 다 넘어야 주식별자
- 후보 중 대표가 주식별자, 나머지가 보조식별자
- 남에게서 받은 값이면 외부식별자
네 질문은 서로 독립이다. 한 식별자가 주식별자이면서 내부식별자이면서 단일식별자이면서 인조식별자일 수 있다. 시험에서 이름 하나를 보면 반사적으로 '이건 어느 질문의 답이지'를 먼저 떠올리자. 그 습관 하나로 이 파트의 오답 대부분이 걸러진다.
궁금한 게 생기면 『빠따 SQLD』 공식 카카오톡 질문방에서 물어보세요. 저자들이 직접 답합니다.
