※ 일본의 한 블로그 글을 번역할 글입니다. 오역 및 직역, 의역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.
시작하기에 앞서
RDBMS의 데이터 베이스 설계(논리)의 작성법에 대해서 설계할 때에, 이러한 부분을 생각하면서 하면 좋을 것 같은 부분에 대해 설명하고자 한다. 그러나 DB 설계에서는 "이것이 정답"이라는 것은 별로 없으며, 요건의 필요조건을 만족하는 DB설계가 정답이라고 할 수 있다. 그렇다고 해도, 고려하는 것이 좋은 부분과 주의점 등이 있으므로 무엇 부터 시작하면 좋을지 고민하고 있는 사람에 참고가 되길 바란다.
DB 설계에 있어서의 포인트
DB 설계할 때에 중요하다고 생각되는 포인트는 다음과 같다.
- 요건/사양을 이해하고 있는가? (요건을 만족하는 테이블/칼럼이 준비되어 있는가?)
- 요건에 없는(잘 보이지 않는) 시스템의 사용을 상정할 수 있는가?
- 레코드를 임의로 식별할 수 있는 키가 존재하는가"
- 필요한 정규화가 되어있는가?
- 장래성을 고려했는가?
테이블의 용어 정리
그나저나 DB의 테이블이 무엇인지 잘 모르겠는 경우 엑셀 표를 떠올리면 이해하기 쉽다. 테이블이란 아래와 같은 표를 DB에서 만드는 것과 같다고 생각하면 된다. 그리고 표를 여러 개 만들어, 테이블간 연결고리를 만든 DB를 RDB(Relational Database)라고 보면 된다.
정보를 정리하여 테이블, 칼럼을 파악한다.
DB 설계를 할 때 반드시 필요한 것이"사양서"이다. 요건, 사양을 이해하지 못했다면 필요한 테이블의 종류나 칼럼의 정의를 할 수 없으므로 먼저 어떤 요건의 어떤 시스템을 구축하는가를 제대로 이해하자.
그리고 요건 정의서나 외부 설계서 등과 함게 정보를 정리하여 테이블과 칼럼 내용을 추려낸다.
1. 테이블의 작성
이번에는 샘플로 간단한 EC 사이트 테이블 정의를 한다고 상정하고 설명을 하도록 하겠다. 요건은 "회원 등록이 가능하며, 상품이 카테고리 분류되어 있고 주문할 수 있다"라는 것이다(원래라면 재고나 출하, 결제 등 많은 테이블이 필요하지만 여기서는 생략한다).
먼저 사양서를 확인하면서 테이블을 점점 추출해낸다. 테이블은 어디까지나 전체를 살펴보면서 조정하기 때문에 여기서너무 많은 시간을 보내지 말고 일단 넘어가자
2. 칼럼의 작성
사양서나 외부 설계서를 확인하면서 테이블 안에 칼럼을 추가한다. 혹은 테이블의 레코드를 식별하는 주키를 결정한다. 레코드 주키가 필요한 이유는 데이터의 갱신이나 삭제를 할 때 대상 레코드를 1개로 특정할 수 있기 때문이다.
즉 테이블에 대해서 INSERT나 UPDATE, DELETE와 같은 조작이 SQL에서 원한 결과대로 실행될지 아닌지의 관점에서 확인하는 것으로 실수를 줄일 수 잇다.
RDB에서는 아래와 같이 주문 테이블 안에 구입한 상품이나 회원의 정보를 장황하게 갖는 것이 아닌 상품 테이블이나 회원 테이블의 주키(상품 ID, 회원 ID)만 입력하는 것으로 테이블 간을 SQL로 연결하는 것이 되므로, 주문 테이블에 상품이나 회원의 정보를 추가할 필요가 없다.
또한 상품의 명칭이나 평가가 변경된 경우에도 주문 테이블에서는 상품 ID만을 갖고 있으므로, 상품 테이블의 정보를 별 다른 걱정없이 갱신할 수 있다.
요건에는 없는(보이지 않는) 시스템의 사양을 상정할 수 있는가?
다음으로 요건으로써는 상품, 주문, 회원이 있지만, 예를 들어 기존에 주문됐던(주문 테이블에 존재하는) 상품을 물리 삭제해도 괜찮을까?(*1) 혹은 언제, 누군가에 의해서 등록된 데이터인지 몰라도 괜찮은가?등 데이터의 정합성이나 나중에 필요해질지도 모를 항목을 상정하여 검토할 필요가 있다.
(*1) 외부 키의 상세한 설명은 여기서 다루지 않겠지만, 외부 키를 붙이는 것으로 테이블 간의 의존 관계가 생성되므로 잘못된 실수를 방지할 수 있다. 그러나 데이터 조작에 있어서 단순히 에러가 날뿐이므로 에러 체크는 어플리케이션 쪽에서 만들 필요가 있다.
따라서 물리 삭제가 되면 곤란한 테이블에는 예를 들어 논리 삭제 플래그를 세워, 상품 ID와 논리 삭제 플래그(0,1)를 주키로 하거나 등록일, 등록자 등 항목을 추가함으로써 언제 누가 조작한 레코드인지 추적하는 등, 사양서에는 적혀져 있지 않은 부분도 고려해서 테이블을 설계해야한다.
정규화를 고려하기
예를 들어, 상품 데이터에 연결되어 있는 카테고리는 아래와 같은 데이터가 등록되어 있다고 가정한다.
카테고리의 예에서 주목해야할 부분은 "가전"이라는 카테고리가 중복되어 있다는 것이다.
여기서, 예를 들어 카테고리 ID이라는 키를 가지고 있는 경우(실제로는 연결할 필요는 없지만 쉽게 설명하기 위해), 상품 ID에 관계 없이 카테고리 ID 만으로 카테고리(예를 들어 가전은 C001, 가구는 C002)를 결정할 수 있다.
이와 같은 칼럼을 분리, 다른 테이블을 만들어 데이터를 이용하기 쉽게하는 것을 정규화(단계에 따라 제 1 정규호, 제 2 정규화, 제 3 정규화 등이 존재)라고 부른다.
요건에 따르겠지만, 기본적으로는 마스터 데이터로써 재이용되기 쉬운 데이터를 다른 테이블로 분리한다. 예를 들어 "가격"도 금액이 중복될 수 있지만, 1엔이라도 다를 때마다 가격 테이블에 데이터를 넣고 상품 테이블과 연결하는 것은 운용이 번거로워지기 때문에 별도의 테이블을 생성하지 않는다.
정규화를 메리트는 "가전"을 "가전제품"으로 변경하고 싶은 경우, 비정규화한 레코드를 갱신할 때 "가전"으로 등록되어 있는 상품 테이블의 레코드 모두를 갱신해야하지만, 별도의 테이블로 분리해둔 경우 카테고리의 "가전" 레코드 1행만 갱신하면 되기 때문에 수정시에 부담이 줄어든다.
또한, 상품 테이블에서 카테고리를 밖으로 빼내는 것으로, 상품이 존재하지 않더라도 사전에 카테고리만을 등록할 수 있다.
- 데이터 갱신시에 부담이 줄어든다.
- 데이터의 장황하게 하지 않음으로써 마스터 데이터의 관리가 용이해져 유지성이 높아진다.
- 데이터의 부정합을 방지한다.
- 마스터 데이터의 재사용 등 확장성이 좋아진다.
(여담) 기본적으로 정규화를 하는 편이 좋지만, 데이터의 갱신이나 삭제가 불 필요하거나, 다른 테이블의 등록, 갱신, 삭제에 의해 데이터의 영향을 받지 않거나, 검색용으로만 사용되는 칼럼 등의 경우 장황한 데이터로 만드는 것이 복잡한 SQL이 불필요하기 때문에 퍼포먼스가 좋아지는 경우가 있다. 따라서 위에서 언급한 경우는 정규화하지 않고, 많은 칼럼을 등록하는 경우가 있다.
장래성을 고려했는가?
이것을 과도하게 할 필요는 없지만, 어느정도 업계 지식이 있는 경우, 테이블을 설계할 때 요건의 누락을 발견하는 경우가 있기 때문에, 설계측의 입장에서 제언이나 조언을 하여 나중에 불필요한 재설계를 방지할 수 있다.
예를 들어, 샘플의 설계에서는 상품에 카테고리가 1개만 연결할 수 있지만, 앞으로 동일 상품에 여러 개의 카테고리를 연결하고 싶을 가능성이 꽤 크다. 이 경우에는 아래와 같이 중간 테이블을 작성한다. 더불어 주문 테이블에도 여러 개의 다른 상품을 구입할 수 있도록 설계를 바꿀 수 있다.
끝으로
데이터 베이스 설계는 맨 처음부터 완벽하게 만들고자 시간을 들여 고민하는 것이 아닌, 테이블과 칼럼을 추려내는 방식으로 일단 대략적으로 만들기 시작하여 만들면서 전체를 조감하면서 추가/수정을 반복하는 것을 추천한다.
또한 한 번에 모두 만드는 것이 아닌 "상품과 카테고리의 관계성을 가진 테이블"을 만들고, 다음에는 "상품과 주문의 관계성을 가진 테이블"을 만드는 등, 작은 단위로 그룹화하면서 만들며, 최종적으로는 전체와 연걸되도록 작업하는 것이 큰 설계에서도 간단한 요건 설계에서도 적용할 수 있는 방법이라고 생각한다.
또한 이번에는 언급하지 않았지만, 전체를 조감하는데 있어서 ER도를 작성하면 도움이 된다.
데이터 베이스 설계를 할 수 있게 되면 시스템 개발의 폭이 넓어짐과 동시에 시스템의 중요점을 확실히 파악할 수 있기 때문에 개발이 즐거워진다!
참고자료
'IT > 기초 지식' 카테고리의 다른 글
[python] 일본 기상청 API 사용하기 (0) | 2022.07.19 |
---|---|
변수 혹은 함수 영어 명명법 (0) | 2022.06.20 |
[github] 멋진 README를 작성하는 방법 (0) | 2022.06.10 |
[git] Github 팀 개발 메뉴얼 (0) | 2022.06.06 |
[Figma] Figma에서 자주 사용하는 단축키 모음 (0) | 2022.06.03 |