← 블로그 목록

참조 무결성은 데이터베이스 규칙이면서 동시에 런타임 안전 규칙이기도 하다

참조 무결성은 외래 키 규칙으로만 생각하기 쉽지만, 런타임에서 포인터·핸들·식별자가 가리키는 대상의 수명을 관리하는 문제에도 거의 같은 구조가 깔려 있다. 데이터베이스가 ‘존재하는 행만 가리키게 하라’고 한다면 런타임은 ‘살아 있는 객체만 가리키게 하라’를 요구한다. 결국 핵심은 소유권과 수명, 유효성 확인을 함께 설계하는 일이다.

참조 무결성은 데이터베이스 규칙이면서 동시에 런타임 안전 규칙이기도 하다

참조 무결성은 데이터베이스 규칙이면서 동시에 런타임 안전 규칙이기도 하다

참조 무결성이라는 말은 보통 데이터베이스에서 먼저 배운다. 테이블 하나의 값이 다른 테이블의 실제 행을 가리키도록 보장하는 규칙이다. 하지만 이 개념은 데이터베이스에서만 중요한 것이 아니다. 프로그램 런타임에서도 비슷한 문제가 계속 나타난다.

포인터, 참조, 핸들, 식별자처럼 어떤 값이 다른 객체를 가리키고 있다면, 그 대상이 정말 존재하는지, 아직 살아 있는지, 바뀌지 않았는지를 계속 관리해야 한다. 결국 참조 무결성은 관계가 깨지지 않게 유지하는 일 전반을 가리키는 말로 읽을 수 있다.


데이터베이스에서의 참조 무결성은 외래 키로 표현된다

PostgreSQL 문서는 Foreign Keys를 설명하면서, 외래 키 제약이 어떤 열의 값이 다른 테이블의 실제 행과 일치해야 한다고 말한다. 즉 존재하지 않는 대상을 가리키는 값을 막는 장치다.

이 규칙이 필요한 이유는 단순하다.

데이터베이스에서는 이런 문제를 외래 키, 삭제 정책, 업데이트 정책으로 다룬다. 핵심은 참조 관계를 사람이 매번 기억해서 맞추지 않게 만드는 것이다.


런타임에서도 같은 종류의 문제가 생긴다

프로그램 안에서도 상황은 비슷하다. 객체 A가 객체 B를 가리키고 있는데 B가 먼저 파괴되면, A가 들고 있던 참조는 더 이상 유효하지 않다. 이건 데이터베이스에서 없는 행을 참조하는 것과 구조적으로 비슷한 문제다.

C++ Core Guidelines는 수명(lifetime) 관련 규칙에서 포인터가 가리키는 객체보다 오래 살아남아서는 안 된다고 명확히 말한다. 이유도 분명하다. 이런 상황은 찾기 어려운 오류와 정의되지 않은 동작으로 이어지기 때문이다.

즉 데이터베이스의 참조 무결성이 존재하는 행만 가리키게 하라는 규칙이라면, 런타임의 참조 무결성은 살아 있는 객체만 가리키게 하라는 규칙에 가깝다.


핵심은 소유권과 수명 관리를 분리해서 생각하는 것이다

참조 무결성이 깨지는 가장 흔한 이유는 누가 소유하는가누가 참조하는가를 섞어 버릴 때다.

그래서 런타임 설계에서는 보통 이런 구분이 중요하다.

데이터베이스가 외래 키와 제약 조건으로 관계를 관리하듯, 프로그램도 소유권 모델과 수명 규칙으로 관계를 관리해야 한다.


핸들, 식별자, 레퍼런스 카운팅은 모두 같은 문제의 다른 해법이다

게임 개발이나 엔진 코드에서는 직접 포인터를 넘기지 않고 핸들이나 ID를 쓰는 경우가 많다. 이유는 객체가 이동하거나 파괴되어도 중앙 관리자에서 유효성을 확인할 수 있기 때문이다.

반대로 참조 계수를 늘려 객체 수명을 연장하는 방식도 있다. 이건 대상을 너무 일찍 파괴하지 않게 해 준다. 다만 순환 참조 같은 또 다른 문제가 생길 수 있다.

어떤 방식을 쓰든 공통 질문은 같다.

  1. 이 참조는 누가 만들었는가
  2. 대상은 언제 파괴되는가
  3. 파괴된 뒤 참조자는 어떻게 알 수 있는가
  4. 참조가 오래 남아도 안전한가

참조 무결성은 결국 이 네 질문에 일관되게 답하는 설계에서 나온다.


핵심 정리

참조 무결성은 데이터베이스의 외래 키 규칙으로만 생각하기 쉽지만, 실제로는 런타임 객체 관리에서도 거의 같은 문제를 다룬다. 존재하지 않는 행을 가리키는 것도 문제고, 이미 파괴된 객체를 가리키는 것도 문제다.

그래서 안전한 프로그램을 만들려면 참조 자체보다 소유권, 수명, 유효성 확인을 함께 설계해야 한다. 데이터베이스와 런타임은 도구는 다르지만, 관계가 깨지지 않게 지켜야 한다는 점에서는 같은 문제를 풀고 있다.

참고 자료

← 목록으로
Related

함께 읽으면 좋은 글

프로그래밍데이터 구조상태 전이
모든 프로그램을 데이터와 상태 전이로 보면 설계가 더 선명해진다

‘모든 프로그램은 데이터베이스다’는 엄밀한 정의는 아니지만 사고 실험으로는 꽤 쓸모 있다. 저장·조회·갱신·삭제, 무결성, 상태 전이의 관점으로 코드를 보면 객체 이름보다 접근 패턴과 유효 상태가 먼저 보이고, 프레임워크가 바뀌어도 설계가 덜 흔들린다. 데이터를 어떻게 다루는지가 결국 프로그램의 성격을 결정한다는 점을 정리한다.

서평C++프로그래밍
『The C++ Programming Language』는 문법책이 아니라 언어 설계 감각을 키우는 책이다

비야네 스트롭스트룹의 『The C++ Programming Language』는 두꺼운 문법서로 보이지만, 실제로는 언어 기능 하나하나를 어떤 설계 판단 아래 써야 하는지를 함께 묻는 책이다. 창안자가 직접 쓴 만큼 ‘할 수 있다’와 ‘해야 한다’를 구분하는 감각이 남으며, 한 단계 올라가려는 C++ 사용자에게 한 번쯤 통과해야 할 책으로 정리한다.

Python코루틴Stackless Python
Stackless Python은 파이썬에 경량 태스크릿과 채널을 더한 구현이다

Stackless Python은 코루틴이 들어간 파이썬이라는 짧은 설명만으로는 부족하다. 태스크릿, 채널, 스케줄러를 통해 매우 가벼운 실행 단위를 다루는 별도 구현이며, PEP 342와 PEP 492가 정착시킨 오늘날의 `async`/`await`와는 다른 계보로 동시성을 메시지 전달과 작은 실행 주체의 협력으로 보게 만드는 관점을 보여 준다는 점을 정리한다.