본문 바로가기
실험실/db이행

이슈

by 죄니안죄니 2026. 1. 15.
반응형

1. Ora11g에서는 thin mode를 지원하지 않음 

Thick버전으로 사용 (파일 경로에 Instanct Client 라이브러리 설치 필요 경로 설정) 

관련 이슈 사용자에게 입력받은 경로의 정합성 검증 

  • 디렉터리 존재 여부
  • 필수 라이브러리 존재 (libclntsh, oci.dll)
  • OS별 파일명 차이 처리

검증 실패 시:

  • 즉시 명확한 에러 메시지
  • 실행 중단

2. 기존 oracle 서버에서는 pk없이 index로만 운영되고 있었던 상황. postgres로 이전하면서 pk를 만들것인가

Oracle이 이걸 버텨준 이유는:

  1. 옵티마이저가 PK 없어도 인덱스 잘 씀
  2. ROWID 기반 접근이 강력
  3. FK 없이도 운영이 가능했던 문화
  4. 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);
중복은 안되지만,  이 row를 대표하는 컬럼 ❌, FK 대상 ❌,  UPDATE/DELETE 안전 기준 ❌

⚠️ 2️⃣ 로그 / 이력 / 적재 테이블

예:

  • 인터페이스 로그
  • 배치 이력
  • 이벤트 로그
  • 집계 임시 테이블

👉 선택지 있음

권장 옵션

  • 의미 없는 BIGSERIAL PK 추가
  • 또는 (created_at, seq) 복합 PK

이유:

  • UPDATE/DELETE 안정성
  • replication 대비
  • 추후 분석/아카이빙 용이

❌ 3️⃣ 정말로 PK 개념이 없는 테이블 (극소수)

예:

  • 순수 raw dump
  • 외부 시스템 그대로 미러링
  • 임시 staging

👉 이 경우만 PK 없이 유지 가능
단, 이건 “운영 테이블”이 아님


“기존 Oracle 구조 그대로 유지”의 위험성

이 선택은 단기적으로 편해 보이지만:

  • FK 못 검
  • 데이터 정합성 보장 불가
  • Postgres 장점을 전혀 못 씀
  • 1~2년 뒤 “이 테이블 왜 이렇게 만들었지?” 회의 열림

👉 기술 부채를 Postgres로 그대로 이전하는 꼴


실무에서 추천하는 최종 전략

✅ 마이그레이션 기준 원칙

  1. 기존 인덱스만 있던 테이블 → 전수 목록화
  2. 테이블별로 분류
    • 업무 / 로그 / 임시
  3. 업무 테이블은 PK 명시
  4. FK는 Postgres에서 다시 걸 수 있게 정리
  5. 애플리케이션 수정 비용이 적은 쪽으로 설계

한 문장 요약

Oracle에서는 “PK 없어도 돌아가던 것”이
PostgreSQL에서는 “언젠가 반드시 터질 구조”가 된다.
업무 테이블이라면 지금 PK를 잡고 가는 게 정답이다.

반응형

댓글