1. Ora11g에서는 thin mode를 지원하지 않음
Thick버전으로 사용 (파일 경로에 Instanct Client 라이브러리 설치 필요 경로 설정)
관련 이슈 사용자에게 입력받은 경로의 정합성 검증
- 디렉터리 존재 여부
- 필수 라이브러리 존재 (libclntsh, oci.dll)
- OS별 파일명 차이 처리
검증 실패 시:
- 즉시 명확한 에러 메시지
- 실행 중단
2. 기존 oracle 서버에서는 pk없이 index로만 운영되고 있었던 상황. postgres로 이전하면서 pk를 만들것인가
Oracle이 이걸 버텨준 이유는:
- 옵티마이저가 PK 없어도 인덱스 잘 씀
- ROWID 기반 접근이 강력
- FK 없이도 운영이 가능했던 문화
- DDL 제약이 느슨해도 성능이 크게 안 무너짐
PostgreSQL에서는 상황이 완전히 다름
PostgreSQL은 철학부터 다릅니다.
1️⃣ PK = “테이블의 정체성”
Postgres에서 PK는 단순 제약이 아니라:
- 옵티마이저 힌트
- FK 참조 기준
- MVCC 기반 업데이트/삭제 안정성
- replication / logical decoding 기준
👉 PK 없는 테이블은 2등 시민 취급입니다.
2️⃣ PK 없는 테이블의 실질적인 문제들
PK 없이 index만 두고 옮기면 실제로 이런 문제가 생깁니다.
✅ 1. UPDATE / DELETE 위험
✅ 2. FK를 걸 수 없음
Postgres에서 FK는 반드시 참조 대상이 PK 또는 UNIQUE여야 합니다.
- 기존 Oracle: 논리적 FK
- Postgres: DDL로 FK 못 걸음
👉 무결성은 전부 애플리케이션 책임
✅ 3. ORM / 프레임워크 문제
- JPA / Hibernate
- MyBatis resultMap
- Spring Data
👉 PK 없는 테이블은:
- Entity 매핑 불가
- @Id 없음 → dirty checking 깨짐
batch update 불가능
✅ 4. 성능 최적화 한계
Postgres 옵티마이저는:
- PK 있으면 “유일함”을 전제로 플랜 생성
- PK 없으면 보수적으로 판단
👉 같은 인덱스라도 실행 계획이 달라짐
그렇다면 “무조건 PK 추가?” → ❌ 아니다
여기서 중요한 실무 판단 포인트가 나옵니다.
테이블 유형별 권장 전략
✅ 1️⃣ 업무 엔티티 테이블 (거의 무조건 PK 추가)
예:
- 고객
- 주문
- 품목
- 거래
- 정산
- 설정 테이블
👉 권장 전략
- 기존 논리 키가 있으면 → 그걸 PK로 승격
- 없으면 → surrogate key 추가 ( Surrogate Key: 의미 없는 인공 PK )
ALTER TABLE orders
ADD CONSTRAINT orders_pk PRIMARY KEY (order_id);
ALTER TABLE log_table
ADD COLUMN id BIGSERIAL PRIMARY KEY;
먼저 한 문장으로 요약 (미리 스포)
Surrogate Key는 “중복 방지용”이 아니라
“데이터가 변해도 절대 흔들리지 않는 기준점”을 만들기 위해 쓴다.
이 문장을 증명해볼게요.
1️⃣ 네가 지금 자연스럽게 떠올리는 생각
“이미 유일한 값이 있는데
굳이 의미 없는 id를 또 만들 필요가 있나?”
예를 들어:
주문번호(order_no)는 유일함
→ 이걸 PK로 쓰면 되잖아?
이 생각 논리적으로 맞음
그래서 “기존 논리 키가 있으면 PK로 승격”이 가능한 거고.
2️⃣ 그런데 문제가 되는 순간은 언제냐
문제는 **“지금”이 아니라 “미래”**에서 터짐
예시 1: 주문번호 정책 변경
기존: ORD-20240101-0001
변경: 2024-01-01-000001
이게 무슨 뜻이냐면:
- PK 값이 바뀜
- 그 PK를 참조하는 모든 FK 테이블 깨짐
- UPDATE 불가능 → DELETE + INSERT
- 데이터 정합성 리스크 폭증
👉 PK는 바뀌면 안 되는 값인데,
비즈니스 키는 바뀔 수 있다
3️⃣ “그럼 바뀌면 같이 바꾸면 되지 않나?”
이 질문이 아주 중요함.
현실 답변: 운영 DB에서는 거의 불가능
이유를 보자.
- FK 걸린 테이블 수십 개
- 로그 / 이력 / 외부 연계 테이블
- 배치, 통계, 캐시
- 과거 데이터 보존
👉 PK 변경은 데이터 구조 변경 사고에 가깝다
4️⃣ 그래서 등장한 개념이 Surrogate Key
사고 전환
“비즈니스 의미 있는 값은
PK로 쓰지 말고
절대 안 바뀌는 가짜 키를 하나 두자”
이게 surrogate key야.
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
이 id는:
- 의미 ❌
- 노출 ❌
- 정책 ❌
- 변경 ❌
👉 그냥 DB 내부 식별자
5️⃣ 그럼 기존 유일한 값은 어디로 가냐?
버리는 게 아님.
UNIQUE (order_no)
- 중복 방지 ✔
- 비즈니스 규칙 ✔
- 조회 조건 ✔
👉 역할 분리
| 역할 | 담당 |
| row 정체성 | surrogate PK |
| 비즈니스 유일성 | UNIQUE |
| 화면/조회 | 논리 키 |
6️⃣ “PK 하나면 충분하지 않나?”가 깨지는 지점
복합 키 예제를 보자 (이게 핵심)
(cust_cd, item_cd, sale_dt)
논리적으로 유일하다고 해도:
- 컬럼 3~5개
- FK 걸 때마다 전부 들고 다녀야 함
- JOIN 복잡
- 인덱스 무거움
- ORM 매핑 지옥
@IdClass(SalesPk.class)
class Sales { ... }
👉 이거 실무에서 다들 싫어함
Surrogate 쓰면?
id BIGSERIAL PRIMARY KEY
UNIQUE (cust_cd, item_cd, sale_dt)
- FK는 id 하나
- JOIN 간단
- 성능 좋음
- ORM 행복
7️⃣ Postgres에서 특히 surrogate가 중요한 이유
Postgres는:
- PK = 옵티마이저 신뢰 기준
- PK = UPDATE/DELETE 안전 기준
- PK = replication 기준
- PK = ORM 기준
👉 PK는 “논리”보다 “안정성”이 우선
8️⃣ 오라클에서는 왜 덜 느껴졌을까?
- ROWID 존재
- PK 없어도 내부적으로 식별 가능
- 관대한 문화
Postgres는:
- “네가 PK 안 줬지? 그럼 내가 모른다.”
9️⃣ 언제 surrogate를 쓰고, 언제 안 써도 되나
✔ Surrogate 쓰는 게 맞는 경우 (대부분)
- 로그 / 이력
- 거래 / 매출
- 다대다 관계
- 복합 키
- ORM 대상 테이블
- FK 많이 걸리는 테이블
✔ 안 써도 되는 경우
- 단일 코드 테이블
- 절대 안 바뀌는 자연 키
- 국가코드
- 통화코드
- ISO 코드
10️⃣ 진짜 핵심 문장 (다시)
Surrogate Key는 “유일성”을 위해 쓰는 게 아니라
“미래에 데이터가 변해도 DB 구조가 무너지지 않게” 쓰는 것이다.
비유 하나로 끝내자
- 비즈니스 키 = 주민등록번호
→ 의미 있음, 바뀔 수 있음, 외부 노출 - Surrogate Key = 내부 직원 번호
→ 의미 없음, 안 바뀜, 내부용
👉 회사 시스템은 직원 번호로 돌아간다
*참고 unique키는 primary key 와 다름
❌ 결정적인 차이
| 구분 | PRIMARY KEY | UNIQUE |
| NULL 허용 | ❌ 불가 | ⭕ 가능 (Postgres) |
| 테이블 대표성 | ✅ 있음 | ❌ 없음 |
| FK 참조 기본 대상 | ✅ | ⚠️ 가능하지만 비주류 |
| ORM @Id | ✅ | ❌ |
| “이 row의 정체성” | ✅ | ❌ |
👉 PK는 테이블을 대표하지만
👉 UNIQUE는 규칙 하나일 뿐
ALTER TABLE sales
ADD CONSTRAINT sales_uk UNIQUE (cust_cd, item_cd, sale_dt);
⚠️ 2️⃣ 로그 / 이력 / 적재 테이블
예:
- 인터페이스 로그
- 배치 이력
- 이벤트 로그
- 집계 임시 테이블
👉 선택지 있음
권장 옵션
- 의미 없는 BIGSERIAL PK 추가
- 또는 (created_at, seq) 복합 PK
이유:
- UPDATE/DELETE 안정성
- replication 대비
- 추후 분석/아카이빙 용이
❌ 3️⃣ 정말로 PK 개념이 없는 테이블 (극소수)
예:
- 순수 raw dump
- 외부 시스템 그대로 미러링
- 임시 staging
👉 이 경우만 PK 없이 유지 가능
단, 이건 “운영 테이블”이 아님
“기존 Oracle 구조 그대로 유지”의 위험성
이 선택은 단기적으로 편해 보이지만:
- FK 못 검
- 데이터 정합성 보장 불가
- Postgres 장점을 전혀 못 씀
- 1~2년 뒤 “이 테이블 왜 이렇게 만들었지?” 회의 열림
👉 기술 부채를 Postgres로 그대로 이전하는 꼴
실무에서 추천하는 최종 전략
✅ 마이그레이션 기준 원칙
- 기존 인덱스만 있던 테이블 → 전수 목록화
- 테이블별로 분류
- 업무 / 로그 / 임시
- 업무 테이블은 PK 명시
- FK는 Postgres에서 다시 걸 수 있게 정리
- 애플리케이션 수정 비용이 적은 쪽으로 설계
한 문장 요약
Oracle에서는 “PK 없어도 돌아가던 것”이
PostgreSQL에서는 “언젠가 반드시 터질 구조”가 된다.
업무 테이블이라면 지금 PK를 잡고 가는 게 정답이다.
'실험실 > db이행' 카테고리의 다른 글
| 서버 데이터 psql insert (0) | 2026.01.16 |
|---|---|
| 이슈 업무범위 ddl까지 vs data 이행까지 (0) | 2026.01.15 |
| 실행모델, Job구조, 상태모델, 보안모델, 결과물 스펙 등 결정사항 (0) | 2026.01.14 |
| 핵심 유즈케이스 (0) | 2026.01.14 |
| 언어선택의 기준 (1) | 2026.01.14 |
댓글