에드거 F. 코드의 관계형 모델이 데이터를 테이블, 키, 규칙으로 바꿔 SQL 기반 데이터베이스가 비즈니스 애플리케이션의 중추가 된 과정을 알아보세요.

가장 단순하게 말하면, 관계형 모델은 정보를 테이블(코드가 ‘릴레이션’이라고 부른 것) 집합으로 저장하고, 공유 값을 통해 서로 연결할 수 있도록 합니다.
테이블은 깔끔한 격자입니다:
비즈니스는 데이터를 고립해서 보관하지 않습니다. 판매는 고객, 제품, 가격, 영업 담당자, 날짜 등으로 구성되고 각 항목은 서로 다른 속도로 변하며 다른 팀이 소유합니다. 초기 시스템들은 이러한 세부를 단단히 결합된, 변경하기 어려운 구조에 저장하는 경우가 많았습니다. 그 결과 보고가 느리고 변경이 위험하며 “간단한 질문”도 비용이 많이 들었습니다.
관계형 모델은 더 명확한 접근을 제시했습니다: 개념별로 별도의 테이블을 유지하고 필요한 때에만 이들을 연결하세요. 고객 세부를 모든 송장 레코드에 복제하는 대신, 고객을 한 번 저장하고 송장에서 참조합니다. 이는 모순(같은 고객의 서로 다른 철자)을 줄이고 업데이트를 더 예측 가능하게 만듭니다.
명확히 정의된 테이블과 이들을 연결하는 규칙을 강조함으로써, 모델은 새로운 기대를 세웠습니다: 많은 사람과 시스템이 동시에 쓸 때도 데이터베이스가 일관성 위반을 방지하도록 도와야 한다는 것 입니다.
코드의 모델은 쿼리 언어는 아니었지만, 영감을 주었습니다. 관련된 테이블에 데이터가 있다면 표준화된 방식이 필요합니다:
이 길은 SQL로 이어졌고, SQL은 모델을 일상 팀들이 비즈니스 데이터에 대해 질문하고 반복 가능하며 감사 가능한 답을 얻는 실용적인 방법으로 바꾸었습니다.
관계형 모델 이전에는 많은 조직이 중요한 정보를 파일에 저장했습니다—종종 애플리케이션마다 하나의 파일을 사용하는 식이었습니다. 급여에는 자체 기록이 있었고, 재고에는 다른 기록이 있었으며 고객 서비스는 또 다른 ‘고객’ 버전을 보관했습니다. 각 시스템은 고립되어 작동했고 그 고립은 예측 가능한 고통을 만들었습니다.
초기 데이터 처리는 보통 맞춤형 파일 포맷과 단일 목적의 프로그램으로 만들어졌습니다. 데이터 구조(각 필드가 어디에 있는지, 레코드가 어떻게 정렬되는지)는 그것을 읽는 코드에 강하게 묶여 있었습니다. 따라서 작은 변경—새 필드 추가, 제품 카테고리 이름 변경, 주소 형식 변경—조차 여러 프로그램을 다시 작성해야 하는 경우가 많았습니다.
팀들이 단일 신뢰 원본을 쉽게 공유할 수 없었기에 데이터를 복사했습니다. 고객 주소는 판매 파일, 배송 파일, 청구 파일 등 여러 곳에 존재했을 수 있습니다.
주소가 변경되면 모든 복사본을 업데이트해야 했습니다. 한 시스템이 누락되면 불일치가 발생했습니다: 송장은 잘못된 곳으로 가고, 배송이 지연되었으며, 지원 담당자는 사용하는 화면에 따라 다른 ‘사실’을 보게 되었습니다. 데이터 정리는 일회성 수정이 아니라 반복되는 프로젝트가 되었습니다.
비즈니스 사용자는 여전히 “제품 X를 구매했다가 반품한 고객은 누구인가?” 같은 질문을 했지만, 답을 얻으려면 함께 작동하도록 설계되지 않은 파일을 이어 붙여야 했습니다. 팀들은 종종 일회성 보고 추출을 만들었고, 이는 또 다른 복사본과 불일치 가능성을 만들었습니다.
결과는: 보고 주기가 느려졌고 “빠른 질문”이 엔지니어링 작업이 되어 버렸습니다.
조직은 여러 애플리케이션이 신뢰할 수 있는 공유 데이터를 필요로 했고, 불일치와 중복 노력을 줄이기를 원했습니다. 또한 기본 저장소를 매번 재구성하지 않고도 새로운 질문을 할 수 있는 방법이 필요했습니다. 그 격차가 코드의 핵심 아이디어에 무대를 마련했습니다: 데이터를 일관되고 애플리케이션 독립적으로 정의해 시스템이 깨지지 않고 진화할 수 있게 하라.
에드거 F. 코드는 영국 출신의 컴퓨터 과학자로, 대부분의 경력을 IBM에서 보냈으며 조직이 정보를 효율적으로 저장하고 검색하는 방법을 연구했습니다. 1960년대에 대부분의 ‘데이터베이스’ 시스템은 잘 관리된 서랍장에 가까웠습니다: 데이터는 엄격하고 사전 정의된 구조로 저장되었고, 그 구조를 바꾸려면 종종 애플리케이션을 다시 작성해야 했습니다. 그 취약성은 조직이 성장하고 요구사항이 변할 때 팀들을 좌절시켰습니다.
1970년, 코드가 발표한 논문 *“A Relational Model of Data for Large Shared Data Banks”*은 놀랍도록 단순한 제안을 했습니다: 데이터를 관련 테이블로 표현하고, 이를 쿼리하고 결합하기 위한 형식적 연산 집합을 사용하라.
높은 수준에서 논문은 다음을 주장했습니다:
코드는 자신의 제안을 집합 이론과 논리학 같은 수학에 근거를 두었습니다. 이는 단순한 학문적 과시가 아니었습니다—데이터베이스 설계에 명확하고 검증 가능한 기반을 제공했습니다. 형식적 모델이 있으면 쿼리가 올바른지, 두 쿼리가 동등한지, 결과를 바꾸지 않고 어떻게 실행을 최적화할지 추론할 수 있습니다. 비즈니스 소프트웨어에서는 이점이 시스템이 확장·진화해도 놀라움이 적다는 것으로 이어집니다.
당시 많은 시스템은 계층형이나 네트워크 모델에 의존해 개발자가 미리 정의된 경로를 따라 데이터를 ‘탐색’했습니다. 코드의 접근법은 데이터베이스가 무거운 작업을 대신해야 한다고 주장하며 그 사고방식에 도전했습니다. 애플리케이션은 저장 레이아웃을 알 필요가 없고, 원하는 결과를 기술하면 데이터베이스가 효율적인 방법을 찾아야 합니다.
이 관심 분리는 SQL과 제품 요구 사항이 바뀌어도 견딜 수 있는 데이터베이스의 무대를 마련했습니다.
코드의 관계형 모델은 간단한 아이디어에서 출발합니다: 사실을 릴레이션(많은 사람들이 테이블로 인식하는 것)으로 저장하되, 그것을 ‘스마트한 스프레드시트’가 아니라 데이터를 기술하는 정밀한 방법으로 취급합니다. 릴레이션은 고객, 주문, 결제, 제품, 배송 같은 비즈니스가 관심을 가지는 사실들에 대한 집합입니다.
릴레이션은 한 종류의 사실 패턴을 나타냅니다. 예를 들어 Orders 릴레이션은 “주문은 ID, 날짜, 고객, 합계가 있다”를 캡처합니다. 핵심은 각 릴레이션이 명확한 의미를 가지며 각 열이 그 의미의 일부라는 점입니다.
행(코드는 이를 튜플이라고 불렀습니다)은 해당 사실의 한 인스턴스입니다: 특정 주문 하나. 관계형 모델에서 행은 고유한 ‘위치’를 갖지 않습니다. 5번 행이 특별한 것이 아니라 값과 그것을 정의하는 규칙이 중요합니다.
열(또는 속성)은 릴레이션의 특정 속성입니다: OrderDate, CustomerID, TotalAmount. 열은 단순한 레이블이 아니라 허용되는 값의 종류를 정의합니다.
도메인은 속성에 허용되는 값의 집합입니다—예: OrderDate에는 날짜, TotalAmount에는 양수, Status에는 제어된 코드 목록(예: Pending, Paid, Refunded). 도메인은 모호성을 줄이고 "12/10/25" 형식 혼용이나 숫자 필드에 "N/A" 같은 미묘한 오류를 방지합니다.
‘관계형’은 사실이 릴레이션 간에 어떻게 연결될 수 있는지를 의미합니다(예: 고객과 주문). 이를 통해 청구, 보고, 감사, 고객 지원 같은 일반적인 비즈니스 작업을 정보 중복 없이 수행할 수 있습니다.
테이블은 자체로 유용하지만, 비즈니스 데이터는 사실을 신뢰성 있게 연결할 수 있어야 의미가 있습니다: 어느 고객이 어떤 주문을 했는지, 어떤 항목이 포함되었는지, 얼마가 청구되었는지 등. 키는 이러한 연결을 신뢰성 있게 만드는 메커니즘입니다.
기본 키는 행을 고유하게 식별하는 열(또는 열들의 집합)입니다. 행의 ‘명찰’로 생각하세요. 중요한 점은 안정성입니다: 이름, 이메일, 주소는 바뀔 수 있지만 내부 ID는 바뀌지 않아야 합니다.
좋은 기본 키는 중복이나 모호한 레코드를 방지합니다. 동일한 이름을 가진 두 고객이 있어도 기본 키는 이를 구분합니다.
외래 키는 다른 테이블의 기본 키를 저장하는 열입니다. 이렇게 하면 모든 데이터를 복사하지 않고 관계를 표현할 수 있습니다.
예시 모델:
외래 키 제약은 가드레일 역할을 합니다. 다음을 방지합니다:
실무적으로 키와 제약은 팀이 보고서와 워크플로를 신뢰하게 합니다. 데이터베이스가 관계를 강제하면 결제, 이행, 고객 지원에서 버그가 줄어듭니다—데이터가 조용히 불가능한 상태로 흘러들어가지 못하기 때문입니다.
정규화는 동일한 사실이 여러 곳에 저장되어 성장하면서 모순으로 흐르는 것을 막는 관계형 모델의 방법입니다. 동일한 사실을 여러 곳에 저장하면 한 복사본만 업데이트하고 다른 복사본을 잊기 쉽습니다. 그 결과 청구서가 잘못된 주소로 가거나 보고서가 일치하지 않거나 어떤 화면에서는 고객이 ‘비활성’으로 보이고 다른 화면에서는 ‘활성’으로 보일 수 있습니다.
실용적 차원에서 정규화는 다음의 일반 문제를 줄입니다:
또한 삽입 이상(주문이 있어야만 고객을 추가할 수 있음)과 삭제 이상(마지막 주문을 삭제하면 고객 정보도 사라짐)을 피합니다.
무거운 이론 없이도 기본 아이디어를 잘 활용할 수 있습니다:
제1정규형(1NF): 각 필드는 원자적이어야 합니다. 고객이 여러 전화번호를 가지면 한 셀에 모두 집어넣지 말고 별도 테이블(또는 별도 행)을 사용하세요.
제2정규형(2NF): 테이블의 식별이 둘 이상의 열에 의존하는 경우(복합 키) 비키 속성은 전체 키에 의존해야 합니다. 주문 항목은 해당 라인의 수량과 가격을 저장해야지 고객 주소를 저장하면 안 됩니다.
제3정규형(3NF): 다른 곳에 속한 ‘부수적 사실’을 제거하세요. 테이블이 CustomerId와 CustomerCity를 둘 다 저장하고 있다면 도시는 보통 고객 테이블에 있어야 하며, 매 주문에 복사하면 안 됩니다.
정규화가 많아지면 테이블과 조인이 늘어납니다. 이는 일관성을 높이지만 보고를 복잡하게 하고 때로는 성능에 영향을 줄 수 있습니다. 많은 팀은 핵심 엔터티(고객, 제품, 송장)에 대해 3NF를 목표로 삼고, 읽기 중심의 대시보드 등에서는 측정된 이유가 있을 때만 선택적으로 비정규화합니다—그러면서도 기본 키/외래 키로 단 하나의 진실 원본을 유지합니다.
관계 대수는 관계형 모델 뒤의 ‘수학’입니다: 한 테이블(행 집합)을 다른 테이블(행 집합)으로 변환하는 작은 집합의 정밀 연산들입니다.
그 정밀함이 중요합니다. 규칙이 명확하면 쿼리 결과도 명확해집니다. 필터링, 형태 변경, 테이블 결합 시 어떤 일이 일어날지 예측할 수 있습니다—문서화되지 않은 동작이나 수동 탐색에 의존하지 않고도요.
관계 대수는 조합 가능한 빌딩 블록을 정의합니다. 가장 중요한 것들 중 세 가지는:
선택(Select): 원하는 행을 고릅니다.
예: “지난달 주문만” 또는 “프랑스 고객만”. 동일한 열을 유지하되 행 수를 줄입니다.
투영(Project): 원하는 열을 고릅니다.
예: “고객 이름과 이메일을 보여줘.” 논리적으로 같은 행을 유지하되 필요 없는 열을 버립니다.
조인(Join): 서로 다른 테이블의 관련 사실을 결합합니다.
예: “각 주문에 고객 세부를 붙여라”, 공유 식별자(예: customer_id)를 사용해 각 행이 원래 따로 저장되던 필드를 함께 담는 새로운 테이블을 만듭니다.
비즈니스 데이터는 자연스럽게 고객, 주문, 송장, 제품, 결제처럼 주제별로 분리됩니다. 그 분리는 각 사실을 한 번만 저장하게 해 불일치를 줄이지만, 답을 얻으려면 사실을 다시 합쳐야 합니다.
조인은 의미를 보존하면서 그 재결합을 수행하는 공식적 방법입니다. 고객 이름을 모든 주문 행에 복사하는 대신 고객을 한 곳에 저장하고 필요할 때 조인해서 보고서를 만드는 방식이 더 낫습니다.
관계 대수는 행 집합에 대한 연산으로 정의되므로 각 단계의 기대 결과가 잘 규정됩니다:
이 개념적 백본이 나중에 SQL을 실용적으로 만든 이유입니다: 쿼리는 애드혹한 데이터 가져오기가 아니라 명확히 정의된 변환의 연속입니다.
코드의 관계형 모델은 데이터가 무엇을 의미하는지(릴레이션, 키, 연산)를 설명했지만 사람들이 일상적으로 사용하기 쉬운 방식을 제시하지는 않았습니다. SQL이 그 빈틈을 메꿨습니다: 관계형 아이디어를 분석가, 개발자, 데이터베이스 제품이 공유할 수 있는 실용적이고 읽기 쉬운 언어로 바꿨습니다.
SQL은 관계 대수에서 영감을 받았지만 코드의 원래 이론을 완벽히 구현하지는 않습니다.
한 가지 주요 차이는 SQL이 결측값( NULL )을 다루는 방식입니다. 고전적 관계 이론은 이중 논리(참/거짓)를 기반으로 하지만 SQL은 NULL을 도입해 3중 논리를 만들었습니다. 또 다른 차이: 관계 이론은 집합(중복 없음)을 전제로 하지만 SQL 테이블은 명시적으로 금지하지 않으면 중복 행을 허용합니다.
그럼에도 불구하고 SQL은 핵심 약속을 지켰습니다: 결과를 기술하면 데이터베이스가 실행 계획을 결정한다는 선언적 접근입니다.
코드가 1970년 기초 논문을 발표했습니다. 1970년대에 IBM은 초기 프로토타입(특히 System R)을 만들어 관계형 데이터베이스가 실제 작업 부하에 대해 충분히 성능을 낼 수 있고 고급 쿼리 언어를 효율적 실행 계획으로 컴파일할 수 있음을 증명했습니다.
학계와 상업적 노력이 병행되어 SQL을 발전시켰습니다. 1980년대 후반에는 ANSI/ISO의 SQL 표준화로 벤더들이 공통 언어에 수렴할 수 있게 되었고, 각 제품은 자체 확장을 유지하더라도 공통 기반을 갖게 되었습니다.
SQL은 질문 비용을 낮췄습니다. 모든 보고서에 대해 맞춤형 프로그램을 작성하는 대신 팀은 질문을 직접 표현할 수 있었습니다:
GROUP BY로 지역/월별 매출비즈니스 소프트웨어에서는 조인과 집계의 조합이 획기적이었습니다. 재무팀은 송장과 결제를 대조할 수 있었고, 제품팀은 전환 퍼널을 분석할 수 있었으며, 운영팀은 재고와 이행을 모니터링할 수 있었습니다—모두 동일한 구조화된 공유 데이터 모델에 쿼리해 얻을 수 있었습니다.
이 사용성 덕분에 관계형 모델은 연구 영역을 넘어 일상 도구로 자리 잡았습니다.
비즈니스 시스템은 신뢰에 달려 있습니다. 단순히 데이터를 저장하는 것만으로는 충분하지 않습니다—다수의 사용자가 동시에 시스템을 쓸 때도 정확한 잔액, 정확한 재고 수량, 신뢰할 수 있는 감사 기록을 보존해야 합니다.
트랜잭션은 여러 변경을 하나의 비즈니스 작업으로 묶습니다. 예: “$100 이체”, “주문 발송”, “급여 반영”. 이런 작업들은 여러 테이블과 여러 행을 건드립니다.
핵심 아이디어는 전부 아니면 전무 행동입니다:
이 방식으로 한 계좌에서 돈이 빠져나갔지만 다른 계좌에 도착하지 않는 상황이나, 주문이 기록되지 않았는데 재고만 줄어드는 상황을 피할 수 있습니다.
ACID는 비즈니스가 의존하는 보장들을 요약합니다:
기본 키, 외래 키, 체크 제약 같은 제약은 잘못된 상태가 기록되는 것을 막습니다. 트랜잭션은 여러 테이블에 걸친 관련 업데이트가 함께 도착하도록 보장합니다.
실무 예: 주문이 저장되고, 주문 항목이 저장되고, 재고가 감소되고, 감사 로그에 항목이 기록됩니다—이 모든 것이 모두 일어나거나 전혀 일어나지 않습니다. 이 조합이 SQL 데이터베이스가 대규모 비즈니스 소프트웨어를 지원할 수 있게 만든 핵심입니다.
관계형 데이터베이스는 유행해서 이긴 것이 아니라 대부분의 조직이 이미 생각하고 일하는 방식과 맞았기 때문에 자리잡았습니다. 회사에는 반복되는 구조화된 것들이 많습니다: 고객, 송장, 제품, 결제, 직원. 각 항목은 명확한 속성 집합을 가지고 서로 예측 가능한 방식으로 연관됩니다. 관계형 모델은 이 현실에 잘 맞아떨어집니다: 고객은 여러 주문을 가질 수 있고, 주문은 항목을 가지며, 결제는 송장과 상계됩니다.
비즈니스 프로세스는 일관성과 추적 가능성에 기반해 구축됩니다. 재무팀이 “어떤 송장이 미지급인가?”라고 묻거나 지원팀이 “이 고객은 어떤 플랜인가?”라고 물어볼 때, 도구나 팀에 상관없이 동일한 답이 나오길 바랍니다. 관계형 데이터베이스는 사실을 한 번만 저장하고 어디서든 참조할 수 있게 설계되어 재작업을 줄입니다.
SQL이 널리 퍼지면서 그 주위에 생태계가 형성되었습니다: 보고 도구, BI 대시보드, ETL 파이프라인, 커넥터, 교육. 이러한 호환성은 채택 비용을 낮추었습니다. 데이터가 관계형 데이터베이스에 있으면 일반적인 보고·분석 워크플로우에 특별한 접착 코드 없이 연결하기가 대개 수월합니다.
애플리케이션은 빠르게 진화합니다—새 기능, 새 UI, 새 통합. 잘 설계된 스키마는 지속 가능한 계약처럼 작동합니다: 서비스와 화면이 바뀌어도 핵심 테이블과 관계는 데이터의 의미를 안정적으로 유지합니다. 이 안정성이 관계형 DB가 신뢰받는 중심이 된 큰 이유입니다.
스키마는 데이터를 조직하는 것뿐 아니라 역할을 명확히 합니다. 팀들은 ‘고객’이 무엇인지, 어떤 필드가 필수인지, 레코드는 어떻게 연결되는지 합의할 수 있습니다. 기본 키와 외래 키로 책임이 명시됩니다: 누가 레코드를 생성하고 누가 업데이트하며 무엇이 비즈니스 전반에서 일관돼야 하는지.
관계형 데이터베이스는 예측 가능하고 안전해서 자리를 잡았지만 모든 워크로드에 최적은 아닙니다. SQL 시스템에 대한 많은 비판은 한 도구를 모든 일에 쓰려는 것에 대한 비판입니다.
관계형 스키마는 계약입니다: 테이블, 열, 타입, 제약이 유효한 데이터를 정의합니다. 공유 이해에는 좋지만 제품이 아직 진화 중인 경우 팀을 지연시킬 수 있습니다.
새 필드를 주간 단위로 출시한다면 마이그레이션, 백필, 배포를 조정하는 것이 병목이 될 수 있습니다. 좋은 도구가 있어도 스키마 변경은 계획이 필요합니다—특히 테이블이 크거나 시스템이 24/7 가동돼야 할 때 더욱 그렇습니다.
“NoSQL”은 관계형 아이디어를 거부한 것이 아니라 특정 고통점에 대한 대응이었습니다:
많은 시스템이 엄격한 일관성이나 풍부한 조인을 포기하는 대신 속도, 유연성, 분산을 얻었습니다.
대부분의 현대 스택은 폴리글랏입니다: 핵심 비즈니스 기록에는 관계형 DB를 사용하고, 이벤트 스트림, 검색 인덱스, 캐시, 문서 저장소는 콘텐츠와 분석용으로 추가합니다. 관계형 모델은 진실의 원천으로 남고 다른 저장소는 읽기 집약적이거나 특수 쿼리에 대응합니다.
선택할 때는 다음에 집중하세요:
좋은 기본값은 핵심 데이터에 SQL을 사용하고, 관계형 모델이 명백한 한계가 될 때만 대안을 도입하는 것입니다.
코드의 관계형 모델은 단지 역사적 사실이 아니라 비즈니스 데이터를 신뢰하고 변경하며 보고하기 쉽게 만드는 습관의 집합입니다. 앱이 여러 저장소를 혼용하더라도 관계형 사고 방식은 주문, 송장, 고객, 재고 같은 “기록 시스템”에 강력한 기본값으로 남습니다.
먼저 비즈니스가 중요하게 여기는 실세계 명사(고객, 주문, 결제)를 테이블로 모델링하고 관계로 연결하세요.
문제를 대부분 예방하는 몇 가지 규칙:
이 원칙을 실제 제품으로 전환할 때는 스키마 의도와 애플리케이션 코드를 정렬해 주는 도구가 있으면 도움이 됩니다. 예를 들어 Koder.ai는 채팅 프롬프트로 React + Go + PostgreSQL 앱을 생성해 정규화된 스키마(테이블, 키, 관계)를 빠르게 프로토타입하고 반복할 수 있게 해 주며, 준비가 되면 소스 코드 내보내기도 할 수 있습니다.
데이터에 강력한 정합성 보장이 필요한 경우 물어보십시오:
대부분의 경우 답이 “예”이면 관계형 데이터베이스가 가장 단순한 경로입니다.
“SQL은 확장할 수 없다”는 지나치게 광범위한 주장입니다. SQL 시스템은 인덱스, 캐시, 읽기 복제, 필요 시 샤딩 등 여러 방식으로 확장합니다. 대부분의 팀은 진짜 데이터베이스 한계에 도달하기 전에 모델링과 쿼리 문제에 직면합니다.
“정규화하면 모든 것이 느려진다”도 불완전한 주장입니다. 정규화는 이상을 줄이고, 성능은 인덱스, 쿼리 설계, 그리고 측정에 근거한 선택적 비정규화로 관리합니다.
코드는 팀에게 공유 계약을 주었습니다: 관련 테이블에 배열된 데이터, 잘 정의된 연산으로 조작되는 데이터, 제약으로 보호되는 데이터. 이 계약 덕분에 일상 소프트웨어는 수년간 진화해도 “무슨 일이 일어났는가, 언제, 왜” 같은 기본 질문에 답할 수 있습니다.
관계형 모델은 데이터를 테이블(릴레이션)로 저장합니다.
핵심 이점은 별도 테이블을 공유 식별자로 연결해 각 사실을 한 곳에만 보관하고 필요할 때 결합해 보고서와 워크플로우를 구성할 수 있다는 점입니다.
파일 기반 시스템은 데이터 레이아웃이 애플리케이션 코드에 강하게 결합되어 있었습니다. 그로 인해 실제 문제가 생겼습니다:
관계형 데이터베이스는 데이터 정의를 특정 애플리케이션과 분리하고 교차 애플리케이션 쿼리를 일상화했습니다.
**기본 키(PK)**는 테이블의 각 행을 고유하게 식별하는 값이며 시간이 지나도 안정적이어야 합니다.
실용적인 지침:
customer_id)를 선호하세요.**외래 키(FK)**는 다른 테이블의 기본 키 값을 담는 열입니다. 전체 레코드를 복사하지 않고도 관계를 표현하는 방식입니다.
패턴 예시:
orders.customer_id는 customers.customer_id를 참조합니다.FK 제약을 활성화하면 데이터베이스가 다음을 방지할 수 있습니다:
정규화는 각 사실을 가능한 한 한 번만 저장함으로써 불일치를 줄이는 것을 목표로 합니다. 실제로 방지하는 문제들:
일반적 목표는 핵심 엔터티에 대해 3NF를 적용하고, 측정된 필요가 있을 때만 선택적으로 비정규화하는 것입니다.
좋은 1NF 규칙: 한 필드에 한 값만 넣으세요.
phone1, phone2, phone3 같은 열이 보이면 별도 테이블로 분리하세요:
customer_phones(customer_id, phone_number, type)이렇게 하면 전화번호 검색, 검증, 업데이트가 쉬워지고 빈 칸 처리 같은 문제가 사라집니다.
관계 대수는 관계형 쿼리의 핵심 연산을 정의합니다:
일상적으로 관계 대수를 직접 쓰진 않아도, 이 개념을 이해하면 SQL 결과를 예측하고 조인에서 의도치 않은 중복을 피하는 데 도움이 됩니다.
SQL은 관계형 개념을 실용적으로 사용할 수 있게 만든 선언적 언어입니다: 원하는 결과를 기술하면 데이터베이스가 실행 계획을 결정합니다.
실무적 성과:
GROUP BY)SQL은 Codd 이론을 완벽히 구현하진 않지만, 관계형 테이블 위에서 신뢰할 수 있는 쿼리를 가능하게 했습니다.
SQL은 순수한 관계 이론과 몇 가지 차이가 있습니다:
NULL은 3값 논리(참/거짓/알 수 없음)를 도입해 필터와 조인에 영향을 줍니다.실무적으로는 NULL 처리를 신중히 하고, 필요한 곳엔 고유성 제약을 강제해야 합니다.
다음 상황이라면 관계형 데이터베이스를 선택하세요:
유연한 스키마, 대규모 분산 등 특정 요구가 있을 때만 NoSQL이나 특화 저장소를 추가하고, 핵심 기록은 관계형으로 유지하는 것이 일반적입니다.