콘텐츠로 이동

논리 모델을 만들어라

28개 언어로도 제공

English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 简体中文 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Русский · Svenska · Dansk · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

Five different dog collars on pegs by a home's front door, each with its own blank metal tag, beside a leash, a brush and a water bowl.
AI로 생성한 이미지

Data Architect 과정 2장인 의미를 위한 데이터 모델링의 모듈 3/6. 각 모듈은 독립적으로 읽을 수 있습니다. 이전: 관계를 그려라 · 다음: 데이터를 제자리에 두라

이 모듈이 답하는 질문: 개념 모델을 어떻게 논리 데이터 모델로 바꿀까요?

개념 모델은 Steve Trucking에 무엇이 있고 그것들이 어떻게 연결되는지 알려 주었습니다. 리테일 파트너와 그들의 물류 센터, 배송 목록과 배송, 수령인, 경로와 정차지, 배송팀, 트럭과 배송팀 배정. 비즈니스와 아주 생산적인 대화를 나누기에는 충분합니다. 하지만 결국 더 많은 세부가 필요합니다. 배송에 대해 무엇을 알아야 하나? 한 물류 센터를 다른 물류 센터와 무엇이 구분하나? 수령인을 어떻게 식별하나? 배송팀이나 트럭이 아니라 배송팀 배정에 속하는 것은 무엇인가? 이런 질문들이 우리를 개념 모델에서 논리 데이터 모델로 이끌고, 우리는 여전히 Salesforce를 만들고 있지 않습니다.

먼저 개들로 돌아갑시다. 상자와 선이 있습니다. 이제 새로운 질문 두 가지입니다. 각 대상에 대해 무엇을 알고 있는가, 그리고 하나를 다른 것과 어떻게 구별하는가?

무엇이 그것을 기술하는가? 개에게는 이름과 생년월일이 있습니다. 주인에게는 이름, 전화번호, 주소가 있습니다. 재주에게는 이름과 난이도가 있습니다. 각 사실은 그것이 기술하는 상자에 들어갑니다.

그다음은 연결입니다. 벨라가 앉아를 얼마나 잘하는지, 언제 배웠는지. 그것은 벨라를 기술할까요? 꼭 그렇지는 않습니다. 벨라는 어떤 재주는 다른 재주보다 잘합니다. 앉아를 기술할까요? 아닙니다. 개마다 앉아를 다르게 합니다. 그것은 벨라와 앉아를 함께 기술하므로, 개 재주에 들어갑니다. 숙련도와 배운 날짜. 연결이 존재하는 이유가 그것입니다. 어떤 사실은 그 쌍에만 속합니다.

어느 개가 어느 개인가? 먼저 이름을 시도해 봅시다. 맥스라는 개는 아주 많으니, 이름은 고유하지 않습니다. 주인의 전화번호는요? 마커스는 같은 전화번호로 개 두 마리를 키우고, 사람들은 번호를 바꾸며, 그것은 누군가의 개인정보이고, 개를 가리키는 모든 시스템에 복사될 것입니다. 마이크로칩 번호가 더 나아 보입니다. 고유하고, 변하지 않습니다. 하지만 새 강아지는 아직 칩이 없을 수 있고, 키는 비어 있을 수 없습니다. 그래서 마이크로칩은 개를 부르는 또 다른 이름으로 남고, 개는 자기만의 개 ID를 받습니다. 개 한 마리를 다른 개와 구별하는, 지루한 일 하나만 하는 번호입니다.

키와 속성을 갖춘 개 모델 상세 데이터 모델로 그린 개 모델입니다. 상자마다 레코드 ID와 필드 몇 개가 나열되어 있습니다. 주인: 주인 ID, 이름, 전화, 우편번호, 도시. 브리더: 브리더 ID, 이름, 도시. 개: 개 ID, 마이크로칩 번호로도 알려짐, 주인 ID와 브리더 ID, 이름, 생년월일. 아직 연결되지 않은 품종: 품종 ID, 이름, 크기. 재주: 재주 ID, 이름, 난이도. 개와 재주 사이의 개 재주: 개 재주 ID, 개 ID와 재주 ID, 숙련도, 배운 날짜. 개 재주 아래의 재주 평가: 자기 ID, 개 재주 ID, 날짜, 숙련도, 평가자. 선은 이전과 같습니다. 주인은 개를 소유하고, 브리더는 개를 번식시키며(개에게는 브리더가 0명 또는 1명), 개는 개 재주를 알고, 재주는 개 재주에서 습득되며, 개 재주는 재주 평가에서 확인됩니다. 소유 번식 앎 습득됨 확인됨 주인 주인 ID 레코드 ID 이름 전화 ZIP 도시 브리더 브리더 ID 레코드 ID 이름 도시 개 개 ID 레코드 ID 마이크로칩 번호 다른 이름 주인 ID 브리더 ID 이름 생년월일 품종 품종 ID 레코드 ID 이름 크기 개 재주 개 재주 ID 레코드 ID 개 ID 재주 ID 숙련도 배운 날짜 재주 재주 ID 레코드 ID 이름 난이도 재주 평가 재주 평가 ID 레코드 ID 개 재주 ID 날짜 숙련도 평가자 정확히 하나 0개 또는 1개 1개 이상 0개 이상 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

이제 같은 질문들을 Steve Trucking에 던질 것이고, 이름, 전화번호, 마이크로칩이 각각 부족한 이유는 제가 수년간 지켜 온 규칙이 됩니다.

개념은 무엇이 있는지, 논리는 그것이 데이터로서 무엇을 뜻하는지 말한다

섹션 제목: “개념은 무엇이 있는지, 논리는 그것이 데이터로서 무엇을 뜻하는지 말한다 ”

트럭을 보십시오. 트럭에 대해 무엇을 알아야 할까요? 차량 번호, 차대번호(VIN), 제조사, 모델, 연식, 번호판, 현재 주행 거리, 상태 정도일 겁니다. 이것들이 트럭의 속성입니다.

이제 배송을 보십시오. 리테일 파트너의 주문 번호, 배송일, 약속된 시간대, 실제 도착 시각, 상태, 설치나 헌 제품 수거 포함 여부 정도일 겁니다. 역시 속성입니다.

개념 모델은 배송이 존재한다는 것을 알려 주었습니다. 논리 모델은 배송이 데이터로서 무엇을 뜻하는지 알려 주기 시작합니다. 트럭이나 배송 같은 단순한 상자 하나가 필드 묶음 전체를 대표할 수 있습니다.

상자에서 속성을 가진 엔터티로 왼쪽에 개념 상자 세 개(트럭, 배송, 물류 센터)가 있고, 각각 “변환” 선으로 오른쪽의 논리 엔터티와 이어져 있으며, 논리 엔터티에는 속성이 나열되어 있습니다. 트럭: 차량 번호, VIN, 제조사, 모델, 연식, 번호판, 현재 주행 거리, 상태. 배송: 파트너 주문 번호, 배송일, 약속 시간대, 실제 도착, 상태, 설치 포함, 수거 포함. 물류 센터: 이름, 주소, 시장, 전화. 개념: 무엇이 있는가 논리: 데이터로서 무슨 뜻인가 변환 변환 변환 트럭 차량 트럭 차량 번호 VIN 제조사 모델 연식 번호판 현재 주행 거리 상태 배송 수령인 한 명에게 주문 하나 배송 파트너 주문 번호 배송일 약속 시간대 실제 도착 상태 설치 포함 수거 포함 물류 센터 배송이 출발하는 곳 물류 센터 이름 주소 시장 전화 이 과정의 다이어그램은 대부분 단순한 상자를 씁니다. 필드는 늘어나고, 낡고, 세부 사항(API 이름, 레이블, 유형, 길이)을 달고 다니기 때문입니다. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

그래도 대부분의 다이어그램에서 상자는 단순하게 유지됩니다. 세 가지 이유 때문입니다. 필드 수는 늘어납니다. 필드는 금세 쓸모없어집니다. 그리고 각 필드에는 개체 모델에 보여 주기 어려운 세부가 있습니다. API 이름, 레이블, 데이터 유형, 길이. 그런 세부는 분명히 기록되지만, 첫 데이터 모델에서는 아닙니다. 핵심 필드 몇 개를 보여 주는 것이 이야기를 전하는 데 정말 도움이 될 때, 저는 상세 데이터 모델을 그립니다. 요점에 중요한 필드만 담은, 초점을 맞춘 단면입니다.

속성은 엔터티를 기술해야 한다

섹션 제목: “속성은 엔터티를 기술해야 한다 ”

속성을 볼 때 쓰는 단순한 질문이 있습니다. 이것은 무엇을 기술하는가? 트럭 제조사는 분명히 트럭을 기술합니다. 그런데 배송에 적힌 배송팀원들의 이름은요? 배송을 기술하나요? 아니면 배송팀을 기술하고, 그 배송팀에게 배송팀 배정이 있었고, 그 배정이 경로를 맡았고, 그 경로에 이 정차지가 있었던 걸까요?

여기서 데이터 모델은 화면에서는 완벽하게 합리적으로 보이는 것들을 드러내기 시작합니다. 코디네이터가 “배송에서 배송팀 이름을 보고 싶어요”라고 말합니다. 정당한 사용자 경험 요구사항입니다. 배송에 배송팀 이름을 저장하라는 요구사항은 꼭 아닙니다. 그 둘은 다른 것이고, 정규화에서 다시 다룹니다. 지금은 이 사실이 실제로 무엇을 기술하는가를 묻는 습관을 들이십시오. 그 질문이 많은 수고를 덜어 줄 것입니다.

그다음 고유 ID 이야기를 해야 한다

섹션 제목: “그다음 고유 ID 이야기를 해야 한다 ”

속성은 대상을 기술합니다. 하지만 풀어야 할 문제가 하나 더 있습니다. 어느 것이 어느 것인지 어떻게 알 수 있나?

수령인 두 명의 이름이 John Smith입니다. 같은 사람일까요? 그럴 수도, 아닐 수도 있습니다. 이름만으로는 부족합니다. 주소? 사람들은 이사합니다. 전화번호는 바뀝니다. 이메일 주소도 바뀝니다. 리테일 파트너의 이름조차 바뀔 수 있습니다.

그래서 키가 등장합니다. 모델에서 무언가를 고유하게 식별하게 해 주는 것입니다. 저는 이 영역에 대해 수년간 꽤 강한 의견을 갖게 되었습니다. 식별자에 대해 저는 네 가지를 원합니다.

고유하고, 변하지 않고, 의미가 없고, 절대 개인정보(PII)가 아니어야 한다.

고유해야 한다. 식별자는 정확히 하나의 대상을 식별해야 합니다. 두 배송이 같은 값을 가질 수 있다면 믿을 만한 배송 식별자가 아닙니다. 이름은 보통 고유하지 않고, 주소도 반드시 고유하지는 않으며, 전화번호는 공유됩니다. 오늘 고유해 보이는 값도 데이터가 충분히 쌓이면 그렇지 않을 수 있습니다. 그러니 물으십시오. 이것 두 개가 같은 값을 가질 수 있는가? 답이 예라면 그것을 레코드의 고유 ID로 쓰는 데 매우 신중하십시오.

변하지 않아야 한다. 이건 자주 놓칩니다. 리테일 파트너를 이름으로 식별하는데 파트너가 이름을 바꾸면, 새 파트너가 생긴 걸까요? 아닙니다. 비즈니스 엔터티는 그대로이고 속성 하나가 바뀌었을 뿐입니다. 레코드의 고유 ID는 그것이 식별하는 대상의 변화에도 살아남아야 하며, 그러면 이름, 이메일 주소, 전화번호, 주소, 사용자 이름은 제외됩니다. 시스템을 처음 만들 때 아무리 편리해 보여도요.

의미가 없어야 한다. 처음 들으면 이상하게 들립니다. 왜 식별자가 의미가 없기를 원할까요? 의미는 바뀌기 때문입니다. 누군가 물류 센터, 리테일 파트너, 배송일, 일련번호를 담은 배송 ID를 만든다고 상상해 보십시오. PHX-KEY-20261002-0042. 영리해 보입니다. 그러다 수령인이 배송을 금요일로 미룹니다. 식별자를 바꿀까요? 안 바꾸면 그 식별자는 거짓말을 합니다. 바꾸면 속성 하나가 바뀌었다고 배송의 고유 ID를 바꾼 것이고, 옛 ID를 저장한 모든 시스템이 그 배송을 놓쳐 버립니다. 식별자가 두 가지 일을 하려 했던 겁니다. 배송을 식별하는 일, 그리고 기술하는 일. 저는 속성이 기술을 맡고 식별자는 지루한 일 하나, 식별만 하게 두고 싶습니다. 지루한 식별자가 좋은 식별자입니다.

절대 개인정보가 아니어야 한다. 이건 따로 둘 만큼 중요합니다. 고유해 보인다는 이유로 개인 식별 정보를 식별자로 쓰지 마십시오. Steve Trucking에서는 전화번호로 수령인을 알아보고 싶은 유혹이 있습니다. 하지만 키는 시스템이 레코드를 연결해야 하는 모든 곳에 복사됩니다. 연동, 내보내기, 로그, 리테일 파트너에게 돌려보내는 상태 파일, 데이터 웨어하우스, 테스트 데이터. 전화번호를 키로 삼으면 수령인의 개인정보를 아키텍처 전체에 퍼뜨린 셈입니다.

키는 또한 모든 레코드에 있어야 합니다. 절대 null이거나 비어 있으면 안 됩니다. 어떤 사람들이 값을 주려 하지 않거나 줄 필요가 없어야 한다면, 그 값은 키가 될 수 없습니다. 그래서 시스템은 자체 내부 식별자를 발급하고, 개인정보는 정말 필요하다면 보호되는 속성이 됩니다.

그래서 제 규칙은 이렇습니다. 고유하고, 변하지 않고, 의미가 없고, 절대 개인정보가 아니어야 한다.

데이터베이스 쪽 사람들에게는 이것들의 일부를 부르는 이름이 있습니다. 자연 키는 비즈니스 데이터에 이미 존재합니다. 트럭의 VIN이 좋은 예입니다. 우리 애플리케이션이 만든 것이 아니고, 이미 의미가 있습니다. 대리 키는 레코드를 식별하려고 특별히 만든 것입니다. 아무것도 기술하지 않고, 그저 식별합니다.

대부분의 아키텍처에서 저는 내부 레코드 ID로 대리 키를 선호하고, 중요한 자연 식별자는 속성으로 둡니다. 자연 식별자가 나쁘다는 뜻이 아닙니다. 아주 중요한 경우가 많습니다. 다만 자동으로 레코드의 고유 ID로 삼지 않을 뿐입니다. 그 값이 수정되거나, 형식이 바뀌거나, 교체되거나, 재사용되거나, 누락되거나, 둘 이상의 원천 시스템에서 들어오면 어떻게 되는지 물으십시오. 단순해 보이는 결정이 아키텍처 결정이 되는 곳이 거기입니다.

하나의 대상에 쓸모 있는 식별자가 여럿일 수 있다

섹션 제목: “하나의 대상에 쓸모 있는 식별자가 여럿일 수 있다 ”

내부 레코드 ID가 다른 모든 시스템이 쓰는 식별자인 것은 아닙니다. Steve Trucking은 배송을 내부적으로 생성된 ID로 식별할 수 있습니다. 각 리테일 파트너는 같은 배송을 자기 주문 번호로 압니다. Keystone은 CSV 배송 목록에서, Redrock은 API에서, Brightwave는 EDI 메시지에서. 그리고 레거시 배차 도구인 RouteDesk의 8년치 이력은 RouteDesk 자체의 배송 ID를 씁니다.

그 식별자들은 중요합니다. 상태 갱신은 각 파트너에게 그쪽의 번호로 돌아가야 하므로, 보관하고 올바르게 매핑해야 합니다. 하지만 그것들이 모두 배송의 고유 ID가 될 필요는 없습니다. “그것의 ID는 무엇인가?”에는 답이 둘 이상일 수 있고, 아키텍트는 어떤 맥락에서 어떤 ID가 권위 있는지 알아야 합니다. 마스터 데이터와 연동에서 다시 다룹니다.

이제 우리가 그린 선으로 돌아가십시오. 배송 목록에는 배송들이 나열됩니다. 수령인은 배송을 받습니다. 배송팀에는 배송팀 배정들이 있습니다. 이 관계들은 양쪽 끝의 대상을 믿을 만하게 식별할 수 있기 때문에 작동합니다.

Steve Trucking에서 문제가 터지는 곳이 여기입니다. 리테일 파트너가 당일에 배송 목록을 수정합니다. 주문 취소, 품목 교체, 새 주소. 수정된 줄을 파트너의 주문 번호로 이미 가진 배송과 매칭하지 못하면, 같은 냉장고에 대한 두 번째 배송을 만들게 되고, 배송팀이 두 번 찾아갈 수도 있습니다. 상자, 속성, 키, 관계는 별개의 아이디어가 아닙니다. 모두 같은 모델의 부분입니다.

초점을 맞춘 상세 데이터 모델 Steve Trucking의 초점을 맞춘 상세 데이터 모델로, 세 그룹으로 나뉘어 있습니다. 각 엔터티에는 레코드 ID(생성된 내부 고유 ID), 다른 이름으로 알려진 ID, 핵심 필드 몇 개가 나열되어 있습니다. 리테일 파트너(이름, 청구 주소, 상태)는 물류 센터를 운영하고 배송을 보냅니다. 배송은 파트너의 주문 번호와 RouteDesk 배송 ID로도 알려져 있으며, 수령인(이름, 주소, 전화, 이메일)에게 배송되고, 물류 센터(이름, 주소, 시장)에서 출발하며, 배송 품목(제품, 수량, 설치 포함)을 포함합니다. 배송팀은 배송팀 배정을 수행하고, 트럭(VIN과 차량 번호로도 알려짐)은 배송팀 배정에 사용되며, 배송팀 배정에는 시작일과 종료일이 있습니다. 고객 데이터 트랜잭션 데이터 참조 데이터 운영 보냄 배송지 출발지 포함 수행 사용됨 리테일 파트너 리테일 파트너 ID 레코드 ID 이름 청구 주소 상태 수령인 수령인 ID 레코드 ID 이름 주소 전화 이메일 배송 배송 ID 레코드 ID 파트너 주문 번호 다른 이름 RouteDesk 배송 ID 다른 이름 배송일 약속 시간대 상태 배송 품목 배송 품목 ID 레코드 ID 제품 수량 설치 포함 배송팀 배정 배송팀 배정 ID 레코드 ID 시작일 종료일 물류 센터 물류 센터 ID 레코드 ID 이름 주소 시장 배송팀 배송팀 ID 레코드 ID 이름 상태 트럭 트럭 ID 레코드 ID VIN 다른 이름 차량 번호 다른 이름 제조사 모델 번호판 상태 정확히 하나 0개 또는 1개 1개 이상 0개 이상 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

이쯤에서 “Salesforce는 모든 레코드에 ID를 주잖아요”라고 생각할 수도 있습니다. 맞고, 거기까지 갈 것입니다. 데이터가 Salesforce에 있다면 모든 레코드는 Salesforce가 생성한 ID를 받습니다. 암호 같고 읽기 어려워서, 보통 사람들이 쓸 수 있는 ID 필드도 함께 노출합니다. D-000184227 같은 배송 번호, 즉 자동 번호(Auto Number) 필드입니다. 사람들은 흔히 그 번호가 레코드의 ID라고 생각하지만 그렇지 않습니다. Salesforce ID는 여전히 그 아래에 있습니다. 외부 시스템이나 Oracle, SQL Server 같은 데이터베이스에도 자체 고유 ID가 있습니다. 하지만 아키텍처에는 결국 Salesforce, 재무 ERP, Snowflake, Data 360, 파트너들의 시스템, 그리고 아직 존재하지 않는 시스템까지 들어갈 수 있습니다. 논리 모델은 모든 결정을 하나의 기술에 기대지 않고 비즈니스 데이터를 기술합니다. Salesforce가 그것을 물리적으로 어떻게 구현할지는 다음 단계입니다.

아키텍트가 여기서 결정하는 것

섹션 제목: “아키텍트가 여기서 결정하는 것 ”

개념 모델을 논리 모델로 바꾸면서, 저는 이것을 결정합니다.

  • 각 엔터티를 실제로 기술하는 속성은 무엇인지.
  • 각 엔터티를 어떻게 고유하게 식별하는지, 그리고 그 식별자가 고유 ID가 될 만큼 안정적인지.
  • 어떤 비즈니스 식별자(파트너 주문 번호, 레거시 ID)를 보관하고 매핑해야 하는지.
  • 민감한 정보가 키로 쓰이고 있는지.
  • 관계가 믿을 만한 고유 ID를 통해 엔터티를 연결하는지.

이제 엔터티, 관계, 속성, 고유 ID가 생겼습니다. 진짜 논리 데이터 모델의 시작입니다. 하지만 아직 문제가 하나 있습니다. 완벽하게 유효한 데이터를 엉뚱한 곳에 넣기가 아주 쉽다는 것입니다. 그래서 정규화가 등장합니다.