데이터 베이스/설계 1편, 현대적 데이터 모델링 완전 정복

Ch07. 논리적 모델링(4) - 식별, 비식별 관계의 SQL 쿼리/성능

webmaster 2026. 6. 27. 13:50

단순 SQL 쿼리

요구사항: 특정 댓글 하나의 내용을 조회하라

 

비식별 관계 쿼리

-- comment_id가 500번인 댓글 조회
SELECT content FROM comment_non_identifying WHERE comment_id = 500;
  • 댓글의 고유 ID 하나만 알면 되므로 매우 단순하고 직관적이다.

식별 관계 쿼리

-- 10번 게시글의 3번째 댓글 조회
SELECT content FROM comment_identifying WHERE board_id = 10 AND comment_no = 3;
  • 댓글을 찾기 위해 부모 ID와 자식 번호를 모두 알아야 한다. 애플리케이션에서 관리해야 할 값이 더 많아진다.

 

SQL 조인과 조회

식별 관계는 손자 테이블을 조회할 조인 없이 데이터를 찾을 있다.

요구사항: "board_id" "1" 모든 대댓글을 찾아라.

 

비식별 관계

ERD

  • reply 테이블에는 "board_id"가 없음, 조인이 필요함
  • 인덱스: 조인을 위한 인덱스가 작고 단순함

식별 관계

ERD

  • reply 테이블에 "board_id"가 있음, reply 테이블만 조회하면 되므로 매우 빠름
  • 인덱스: 크고 무거운 복합 인덱스

단일 식별자의 장점: 단순함이 주는 강력함

식별자가 하나라는 것은 단순히 WHERE 절이 짧아지는 이상의 이점을 가진다. 이는 소프트웨어 전체의 복잡도와 직접적으로 연결된다.

  • API 및 URL 설계의 단순성
    • 웹 애플리케이션에서 특정 데이터를 가리키는 URL을 설계한다고 생각해 보자.
    • 비식별 관계: 특정 댓글을 가리키는 주소는 "/comments/500"처럼 매우 명확하고 직관적이다.
    • 식별 관계: "/boards/10/comments/3"과 같이 부모의 정보까지 경로에 포함되어 더 길고 복잡해진다.
    • 댓글을 독립적인 자원(Resource)으로 다루기보다 부모에게 종속된 형태로 다루게 되어 유연성이 떨어진다. 식별자 값도 2개 사용해야 한다.
  • 개발 편의성 및 실수 방지
    • 애플리케이션 코드(Java, Python 등)에서 댓글을 다루는 함수를 만든다고 가정해 보자.
    • 비식별 관계: "deleteComment(commentId)"처럼 파라미터 하나만 받으면 되므로 함수를 만들고 사용하기가 매우 쉽다.
    • 식별 관계: "deleteComment(boardId, commentNo)"처럼 두 개의 파라미터를 받아야 한다.
      • 개발자가 실수로 두 값의 순서를 바꾸어 넣는 버그가 발생할 수도 있고, 데이터를 전달하는 과정 전체가 더 번거로워진다.
  • 객체지향 및 ORM과의 조화
    • 현대 개발에서는 JPA/Hibernate 같은 ORM 기술을 많이 사용하는데, 이는 데이터베이스의 테이블을 코드의 객체(Object)와 매핑하는 기술이다.
    • 비식별 관계: Comment라는 객체는 "id"라는 하나의 필드로 명확하게 식별된다. 이는 객체지향의 원칙과도 잘 맞으며, ORM 프레임워크가 가장 자연스럽고 효율적으로 처리할 수 있는 구조다.
      • "repository.findById(500L)"와 같이 매우 단순한 코드로 데이터를 조회할 수 있다.
    • 식별 관계: ORM에서 복합키를 다루려면 별도의 식별자 클래스(CommentId)를 만드는 등 훨씬 복잡하고 번거로운 추가 작업이 필요하다. 이는 코드의 양을 늘리고 유지보수를 어렵게 만든다.
      • 관계의 계층이 깊어져서 만약 식별자가 2개가 아니라 3 ~ 4개라고 생각해 보자. 지금보다 훨씬 더 복잡할 것이다.

 

결론적으로, 단일 식별자를 사용하는 비식별 관계는 데이터베이스뿐만 아니라, 그 데이터를 사용하는 애플리케이션의 모든 계층(API, 비즈니스 로직, 데이터 접근 등)을 더 단순하고 견고하게 만들어주는 핵심적인 설계 원칙이다.

 

식별 관계 vs 비식별 관계 - 인덱스 사용

데이터베이스 성능은 인덱스를 얼마나 활용하느냐에 달려있다. 관계는 인덱스 구조와 활용 방식에서 미묘하지만 중요한 차이를 보인다.

 

요구사항: "10 게시글에 달린 모든 댓글을 조회하라."

 

비식별 관계의 인덱스 전략

comment_non_identifying 테이블은 기본적으로 PK "comment_id" 대한 UNIQUE INDEX 가진다. 지만 요구사항의 쿼리(WHERE board_id = 10) 빠르게 처리하려면, FK "board_id" 컬럼에 별도의 인덱스 생성 주어야 한다.

CREATE INDEX idx_comment_board_id ON comment_non_identifying (board_id);
  • 이 인덱스가 없다면, 데이터베이스는 comment_non_identifying 테이블 전체를 스캔(Full Table Scan) 해야 하므로 댓글이 많아질수록 성능이 급격히 저하된다.
  • 인덱스를 생성하면 "board_id"를 기준으로 매우 빠르게 데이터를 찾을 수 있다
참고

MySQL의 경우 외래 키 제약조건을 설명하면 자동으로 인덱스를 생성한다. 만약 외래 키 제약조건을 사용하지 않는다면 반드시 인덱스를 생성해야 한다.

 

식별 관계의 인덱스 전략

comment_identifying 테이블은 "(board_id, comment_no)" 대한 PRIMARY KEY INDEX 가진다. 인덱스는 인덱스의 번째 컬럼을 기준으로 쿼리할 효율적으로 동작한다. "WHERE board_id = 10" 쿼리는 복합 PK 인덱스의 번째 컬럼인 "board_id" 조건으로 사용하므로, 별도의 인덱스 생성 없이도 매우 빠르게 동작한다.

 

성능 관점에서의 결론

  • 식별 관계는 부모-자식 순으로 데이터를 조회하는 특정 시나리오(예: 게시글의 모든 댓글 조회)에서 별도의 인덱스 생성 없이도 높은 성능을 보일 수 있다.
  • 비식별 관계는 필요에 따라 FK 컬럼에 인덱스를 직접 생성해야만 동일한 성능을 확보할 수 있다.

 

실무에서는 어떨까?

"그렇다면 성능을 위해 식별 관계가 좋은 아닌가?"라고 생각할 있다. 하지만 그렇지 않다. 비식별 관계에서 FK 인덱스를 하나 추가하는 것은 전혀 어려운 일이 아니며, 현대 데이터베이스 시스템에서는 일반적인 최적화 기법이다. 인덱스 하나를 추가함으로써 식별 관계의 모든 단점(복잡성, 유연성 부족) 피하고 비식별 관계의 장점(단순성, 확장성) 모두 누릴 있다.

따라서 사소한 인덱스 최적화의 이점을 위해 설계 전체의 유연성을 희생하는 것은 현명한 선택이 아니다.