데이터베이스를 다루다 보면 SEQ, NO, ID 같은 순번 컬럼을 흔하게 만나게 됩니다. 특히 데이터를 이관하거나(AS-IS → TO-BE) 테이블 설계를 리뷰할 때, 이 SEQ 컬럼의 정체 때문에 골머리를 앓는 경우가 많습니다.
"AS-IS에서는 환자별, 날짜별로 1, 2, 3... 순번이 매겨졌는데, TO-BE에서는 그냥 전체 데이터에 1부터 쭉 번호가 붙었어요. 이거 잘못된 거 아닌가요?"
이런 고민, 한 번쯤 해보셨을 겁니다. 결론부터 말하면, 두 SEQ는 완전히 다른 의미를 가집니다. 오늘은 이 두 가지 방식, '그룹 내 순번(Group Sequence)'과 '전역 일련번호(Global Sequence)'의 개념과 각각 언제, 왜 사용해야 하는지 명쾌하게 정리해 보겠습니다.
1. 두 종류의 SEQ: 도서관 사서처럼 생각해보기 📚
두 개념을 쉽게 이해하기 위해 도서관을 비유해 보겠습니다.
AS-IS 방식: "그룹 내 순번" (책꽂이의 n번째 책)
- 개념: 특정 그룹 안에서만 순서대로 증가하는 번호입니다. 그룹이 바뀌면 번호는 다시 1부터 시작합니다.
- 예시: (환자번호, 입원일자)가 같은 데이터 그룹 내에서 1, 2, 3... 순으로 번호가 매겨지는 방식
- 도서관 비유: '컴퓨터 과학' 책꽂이의 3번째 책, '인문학' 책꽂이의 1번째 책처럼, 특정 '책꽂이(그룹)' 안에서의 위치를 나타내는 번호입니다. 책꽂이가 바뀌면 순번은 새로 시작되죠.
이 번호는 그 자체로 "해당 환자의 해당 입원일에 발생한 n번째 이벤트"라는 강력한 업무적 의미를 가집니다.
TO-BE 방식: "전역 일련번호" (도서관의 등록번호)
- 개념: 테이블 전체에서 유일하며, 데이터가 추가될 때마다 계속해서 증가하는 번호입니다.
- 예시: 데이터가 쌓일 때마다 1, 2, 3, ... 100, 101... 행의 개수만큼 무조건 증가하는 방식
- 도서관 비유: 책의 장르나 위치와 상관없이 도서관에 들어오는 모든 책에 부여되는 고유 등록번호(바코드)와 같습니다. 이 번호만 알면 도서관의 어떤 책인지 유일하게 식별할 수 있습니다.
이 번호는 업무적 의미보다는, 각 데이터를 유일하게 식별하기 위한 기술적인 식별자(Surrogate Key) 역할을 합니다.
2. 그래서, 언제 무엇을 써야 할까요? (핵심 사용처 비교)
이제 어떤 상황에서 각 방식을 사용해야 하는지 명확히 구분해 보겠습니다.
✅ "그룹 내 순번"이 반드시 필요한 경우
- 그룹 내 순서가 업무 규칙일 때
- "첫 번째 처방(seq=1)에만 보험 적용"
- "동일 입원 건에 대한 마지막 검사(가장 큰 seq) 결과만 유효"
- 이처럼 'n번째'라는 순서가 비즈니스 로직에 직접 사용될 때 반드시 필요합니다.
- 데이터의 발생 순서를 명확히 해야 할 때
- 로그 데이터나 이벤트 데이터처럼, 특정 조건 하에서 발생한 순서가 중요한 경우 사용됩니다.
- 복합 키(Composite Key)의 일부로 유일성을 보장할 때
- 사용자 질문처럼 (환자번호, 입원일자)만으로는 데이터가 중복될 수 있을 때, seq를 추가하여 (환자번호, 입원일자, seq)로 PK를 구성해 유일성을 확보합니다.
SQL로 구현하기 ROW_NUMBER() OVER (PARTITION BY 그룹핑할_컬럼 ORDER BY 정렬할_컬럼) AS group_seq 와 같은 윈도우 함수(Window Function)로 쉽게 생성할 수 있습니다.
✅ "전역 일련번호"가 유리한 경우
- 단순하고 안정적인 PK가 필요할 때
- 환자번호, 입원일자 같은 업무 키(Natural Key)는 정책 변경, 데이터 정정 등으로 값이 변경될 수 있습니다.
- 전역 일련번호는 한 번 부여되면 절대 변하지 않으므로, 데이터의 무결성을 지키는 데 매우 유리합니다.
- JOIN 성능과 FK 관리를 단순화하고 싶을 때
- 나쁜 예: PK가 (환자번호, 입원일자)라면, 이 데이터를 참조(FK)하는 모든 테이블은 이 두 개의 컬럼을 항상 같이 가져가야 합니다. JOIN 조건도 복잡해지죠.
- 좋은 예: PK를 visit_id (전역 일련번호)로 두면, 다른 테이블에서는 visit_id라는 단 하나의 숫자 컬럼만으로 관계를 맺을 수 있어 모델이 단순해지고 JOIN 성능도 향상됩니다.
- 업무와 기술을 분리하고 싶을 때
- PK는 기술적인 식별자(전역 일련번호)에게 맡기고, 업무적인 유일성 보장은 UNIQUE 제약조건 (환자번호, 입원일자)에 맡기는 것이 현대적인 데이터 모델링의 좋은 패턴입니다.
3. 주의! 전역 시퀀스를 쓰지 않는 게 나을 때도 있다? ⚠️
전역 시퀀스가 만능은 아닙니다. 다음과 같은 상황에서는 사용을 재고해야 합니다.
- 자연키만으로 식별이 안정적이고, FK/조인도 단순한 경우
- 예: (환자번호, 입원일자)가 업무적으로 단 한 건만 존재하고, 변경 가능성도 매우 낮음.
- 이때 전역 SEQ PK를 추가하면 스키마 복잡도만 늘고, FK에도 불필요한 컬럼이 하나 더 생깁니다.
- “전역 id + 자연키 Unique”의 이중 제약이 중복 관리 비용이 될 수 있습니다.
- 예: (기관코드, 외래진료일자)처럼 업무 규칙 자체가 키 제약인 경우.
- 전역 SEQ를 PK로 두면 자연키는 단지 Unique 제약이 되어 모델링 가시성이 떨어집니다(ERD에서 핵심 규칙이 잘 안 보임)
결론의 핵심 전제: '중복 가능성'의 유무
가장 먼저 스스로에게 던져야 할 질문은 이것입니다.
"정말로 우리 시스템에서 환자번호 + 입원일자 조합은 과거, 현재, 미래를 통틀어 절대로 중복이 발생하지 않는다고 100% 확신할 수 있는가?"
이 질문에 대한 대답에 따라 설계 방향이 결정됩니다.
상황 1: YES. 절대 중복이 발생할 수 없다.
이 경우, (환자번호, 입원일자) 조합만으로도 모든 행을 유일하게 식별할 수 있습니다. 따라서 유일성 확보를 위한 group_seq는 필요 없습니다. 모든 데이터의 group_seq는 항상 '1'이 될 것이므로 중복(redundant)된 정보일 뿐입니다.
이때의 최적 설계는 다음 두 가지 중 하나입니다.
- 자연키 PK: (환자번호, 입원일자)를 그대로 PK로 사용합니다. (가장 직관적)
- 대리키 PK: id(전역 시퀀스)를 PK로 두고, (환자번호, 입원일자)는 UNIQUE 제약조건으로 설정합니다. (FK 관계가 많을 때 유리)
결론: 이 시나리오에서는 group_seq를 사용하는 것은 좋은 설계가 아닙니다.
상황 2: NO. 지금은 아니더라도, 중복 가능성이 조금이라도 있다.
- 같은 날 퇴원했다가 응급실로 다시 재입원하는 경우
- 오전에 외래 진료, 오후에 다른 과에서 또 외래 진료를 받는 경우
- 데이터 입력 실수로 중복이 발생하는 경우
이처럼 비즈니스적으로나 시스템적으로 동일한 (환자번호, 입원일자)에 여러 건의 데이터가 쌓일 가능성이 있다면, 그때는 group_seq가 유일성을 보장하는 핵심적인 역할을 하게 됩니다.
이때의 최적 설계가 바로 블로그에서 제안한 "둘 다 쓰는" 방식입니다.
- PK = id (전역 시퀀스, 기술적 식별자)
- UNIQUE Key = (환자번호, 입원일자, group_seq) (업무적 식별자)
결론: 이 시나리오에서는 group_seq가 반드시 필요하며, 전역 시퀀스와 함께 사용하는 것이 가장 이상적입니다.
'DB' 카테고리의 다른 글
뷰(view) (0) | 2025.09.25 |
---|---|
[SQL 튜닝] 함수는 죄가 없다. JOIN, 서브쿼리, 함수 제대로 알고 쓰기 (1) | 2025.08.30 |
데이터 마이그레이션 전환 검증 전략 (5) | 2025.08.03 |