Show 회원 가입 및 로그인을 위한 테이블 설계로 보는 1:1 정규화 분리개발자의 글쓰기라는 책을 읽다보면 이런 에피소드가 나옵니다. 문장을 주고 특정 핵심 단어로 문장을 요약을 해보라고 했을때 DBA는 추려낸 단어에서 중복된 단어는 제거 해야한다고 말한다고 하죠. 이처럼 습관적으로 데이터 중복에 민감한을 표출하는 사람들이 DBA입니다. 많은 데이터베이스 이론들이 정규화의 필요성을 강조합니다. 정규화를 통해 데이터 중복을 피하고, 무손실 분해, 종속성 유지 분해의 조건이 갖춰지면 데이터 무결성, 종속성 등을 유지할 수 있습니다. 보이스 코드 정규화 (BCNF)를 구현이 가능하면 가장 좋지만, 최소 3정규화까지는 구현을 해야 데이터의 구조적인 문제에서 오는 데이터 중복을 막을 수 있으며, 데이터 중복은 불필요한 공간을 차지하는 문제 뿐만 아니라, 데이터베이스 I/O처리에서 많은 문제를 불러오기 때문에 데이터 중복을 제거하는 것은 데이터베이스를 다루는데 있어서 중요한 부분입니다. 왜냐하면 데이터베이스의 성능을 결정 짓는건 바로 I/O이며, 데이터 중복은 이런 읽기나 쓰기에 대한 I/O를 증가시키기 때문에, 많은 DBA와 DA들이 I/O를 줄이기 위하여, 정규화를 하고 SQL튜닝을 하고 하는 것이죠. 데이터의 속성에 따라 정규화 할 필요가 있다고 이론서들은 늘 말합니다. 하지만 그 속성을 어떻게 나누고, 분류할 것인지 결정하는 것은 어려운 문제입니다. DBA나 DA가 없는 상황에서 개발자들이 서비스에 필요한 수준으로 설계해서 구성된 DB들은 이런 기본적인 원칙이 잘 지켜지지 않습니다. 후에 DB 성능에 문제가 발생한 시점에서는 구조적인 문제가 너무 엉망으로 얽히고 꼬여있어서 손을 댈 수 없는 상황이 많습니다. 1:1 항목에 대해서는 굳이 테이블 분리를 할 필요가 없다라고 말하시는 분들도 있습니다. 하지만 데이터가 많아지고, 서비스가 커지면 한 테이블에 너무나 많은 컬럼이 담겨 있어 문제가 되는 경우가 반드시 발생합니다. 데이터베이스는 인덱스를 사용하던, 풀스캔을 하던, 특정 값을 읽어오기 위해서는 그 값이 들어있는 row의 전체 블록에 대한 읽기 작업이 선행됩니다.
RDBMS에서 row는 데이터를 입/출력하는 최소 단위 이기 때문에 컬럼이 많으면 많을 수록 어쨌든 블록의 읽기가 많아진다는 것이 사실입니다. 1:1 매칭이라고 해서 컬럼을 마구마구 늘렸다가 속성값이 안맞는 값이 들어가 있고, 후에 안쓰는 컬럼이 생기고 하다보면 나중에 구조적인 문제 뿐만 아니라 성능 이슈 역시 발생하는 것이죠. 다수의 컬럼, 즉 데이터가 많은 테이블의 row를 불러올 때, 다른 비슷한 컬럼이 많은 테이블과 Join을 한다고 가정하면 실제 필요한 데이터보다 훨씬 많은 블록을 읽어와 결과 값을 출력해야 하며, 데이터가 쌓여 갈 수록 점점 더 느려지는 결과를 가져옵니다. 이렇게 컬럼이 많은 구조에서는 복합 인덱스를 잘 구성하면 어느정도 해소가 가능하지만, 컬럼이 한테이블에 100개씩 존재하는 구조에서는 어찌됐든 성능이 잘나오길 바라는건 무리죠. 회원 테이블의 비지니스 로직과 구조화하기유저 테이블 경우 한번 구성을 하게되면 거의 모든 서비스에서 참조하는 테이블입니다. 따라서 유저 테이블은 불필요한 데이터가 많다거나 컬럼이 많다거나 하면 좋지 않아요. 그리고 속성이 다른 데이터들이 많아 1:1 매칭이 되더라도, 정규화를 하여 분리하는 것이 좋습니다. 회원 테이블은 회원 가입과 로그인에 가장 먼저 사용되고, 이후 서비스가 돌아가면, 정산을 한다거나 통계나 서비스 이용 목록 등을 조회할 때 계속 사용이 됩니다. 이건 모든 서비스가 이런 비지니스 로직을 가진다는 것은 아니고, 일반적이고 심플한 앱 서비스를 기준으로 그려본 것 입니다. 일반적인 회원가입과 로그인이 대부분 이런식의 로직으로 동작을 합니다. 그에 따라 테이블 설계도 이런 로직을 커버할수 있도록 설계가 되야합니다. RDBMS 테이블 설계MySQL을 기준으로 작성을 했고, 한 인스턴스 안에 스키마 단위로 첫번째 분리가 되었고, ERD의 레이어 단위가 스키마라고 보면 됩니다. 이런식으로 스키마를 통한 분리를 하는것은 SQL 인젝션 공격에 대한 방어가 첫번째이고, 속성 별로 나누어 나중에 서비스 규모가 커지더라도 스키마를 쉽게 인스턴스로 분리하여 MSA까지 고려하는 구성입니다. member 스키마부터 살펴 보겠습니다.member.user
member.authentication
member.profile
member.subscription
member.device
그 다음은 auth 스키마 입니다.auth.password
auth.social_login
auth.cidi
휴면(dormant) 스키마 입니다.
탈퇴(withdrawal) 스키마 입니다.
Log 스키마의 오브젝트들을 보면 기존 테이블과 구성이 다릅니다.
앱서비스에 필요한 기본적인 테이블 설계를 통해 어떻게 1:1 매칭 데이터들이 어떤 속성을 가지고 분리 되는지 위 ERD 모델을 보고 천천히 분석해보면 테이블 모델링에 대해 조금은 이해가 되지 않을까 해서 그려봤습니다. 또한 14세 미만 부모 동의나 성인 인증이 필요한 경우도 저 모델에서 어디에 어떻게 추가하면 될까 스스로 고민해보시면 앞으로 새로운 설계를 하는데 많은 도움이 될 것이라 생각합니다. 1:1 정규화를 통해서 join을 해야하는 테이블들 간의 블록 읽기를 최소화 하면 데이터 출력 속도도 빠르게 유지할 수 있고, 속성 별로 테이블을 분리 했기 때문에 적재적소에 필요한 컬럼이나 별도의 테이블을 추가해서 서비스를 늘려가는 것이 어렵지 않습니다. 테이블정의서를 첨부합니다. Post Views: 151 |