# Oracle 계보 (As-Is) — acquire-core-x

> **이 시스템의 원본은 Oracle 이다.** BC 매입시스템 As-Is 는 Oracle 19c + Pro\*C +
> Tuxedo/ATMI 였고(BAIS RFI 기준), 본 저장소의 현행 코드는 그 시스템을 오픈 스택
> (Enduro/X + ECPG + PostgreSQL)으로 **이식한 1차 이관본**이다. Klaro Forge 가
> 수행할 다음 이관은 이 레거시 → Java Spring Boot 다.
>
> `legacy-oracle/` 에 **As-Is Oracle Pro\*C 역사 원본**을 보존한다(컴파일 대상 아님).
> 현행 이식본(`app/src/**/*.pgc`, ECPG/PostgreSQL)과 1:1로 대조 가능하다.

## 3단 계보

```
  ┌── As-Is ───────────┐   ┌── 현행(1차 이관본) ─────┐   ┌── To-Be (Forge) ──────┐
  │ Oracle 19c          │   │ PostgreSQL 16           │   │ PostgreSQL 16          │
  │ Pro*C (proc)        │ → │ ECPG (EXEC SQL)         │ → │ JPA / MyBatis          │
  │ Tuxedo/ATMI         │   │ Enduro/X (open ATMI)    │   │ Spring Boot 3.x        │
  │ PL/SQL 패키지        │   │ (패키지→서비스 인라인)   │   │ @Service / @Transactional
  │ legacy-oracle/*.pc  │   │ app/src/**/*.pgc        │   │ (target)               │
  └─────────────────────┘   └─────────────────────────┘   └────────────────────────┘
```

- As-Is → 현행: **DB 엔진 이관**(Oracle→PostgreSQL)은 끝났다. Oracle 방언·Pro\*C·PL/SQL
  패키지를 PostgreSQL/ECPG 로 옮긴 결과가 현행 코드다.
- 현행 → To-Be: 남은 난제는 **애플리케이션 계층**(ATMI·임베디드SQL·UBF·XA)이며,
  이게 Forge 가 다룰 대상이다. DB 엔진은 이미 PostgreSQL 이라 To-Be 와 일치한다.

## Oracle → PostgreSQL 방언 이관 매핑 (1차 이관에서 실제로 옮긴 것들)

| Oracle (As-Is, Pro\*C) | PostgreSQL (현행, ECPG) | 이관 난이도·주의 |
|---|---|---|
| `VARCHAR2(n)` / Pro\*C `VARCHAR h[n]` | `TEXT` / `char h[n]` | 널·공백 트림 의미 차이 |
| `NVL(x, d)` | `COALESCE(x, d)` | 인자 개수 차이(NVL2→CASE) |
| `DECODE(e, k1,v1, k2,v2, d)` | `CASE WHEN e=k1 THEN v1 ... ELSE d END` | 다분기 전개, NULL 동등성 차이 |
| `SYSDATE` / `SYSTIMESTAMP` | `now()` / `current_date` | 시간대·타입 차이 |
| `... FROM DUAL` | (FROM 절 생략) | 시퀀스·스칼라 조회 재작성 |
| `seq.NEXTVAL` / `seq.CURRVAL` | `nextval('seq')` / `currval('seq')` | 문법·세션 시맨틱 차이 |
| `ROWNUM = 1` / `ROWNUM <= n` | `LIMIT 1` / `LIMIT n` | ROWNUM 은 정렬 前 적용 → 의미 함정 |
| 외부조인 `t1.a (+) = t2.b` | `LEFT/RIGHT JOIN ... ON` | 구식 `(+)` 전면 재작성 |
| `CONNECT BY PRIOR` 계층질의 | `WITH RECURSIVE` CTE | 계층 재귀 완전 재작성(최난이도) |
| `TO_DATE(s,'YYYYMMDD')` / `TO_CHAR(d,fmt)` | `to_date`/`to_char` (포맷토큰 일부 상이) | 포맷 마스크 검증 필요 |
| `(+)`/`MINUS`/`ROWID` | `EXCEPT`/`ctid`(비권장) | 세트연산·행식별자 대체 |
| Pro\*C `EXEC SQL WHENEVER SQLERROR GOTO` | ECPG 동일 문 + `sqlca.sqlcode` 분기 | 라벨분기 유지 가능 |
| Pro\*C `EXEC SQL INCLUDE oraca` / `EXEC ORACLE OPTION` | (해당 없음) | Oracle 전용 진단영역 제거 |
| **PL/SQL 패키지** (`pkg_x.proc`) | ECPG 서비스 인라인 / 함수 | 패키지 상태·오버로드 소실, 로직 서비스로 흡수 |
| `RAISE_APPLICATION_ERROR(-20001,...)` | `RAISE EXCEPTION` / 리턴코드 | 예외 프로토콜 재설계 |
| `UTL_FILE` 파일 I/O | 서버 파일 I/O / COPY | 배치 파일생성 재작성 |

## As-Is 원본 보존 목록 (`legacy-oracle/`)

| 원본 (Oracle Pro\*C / PL-SQL) | 현행 이식본 (ECPG) | 업무 |
|---|---|---|
| `proc/ACQUIRE.pc` | `app/src/ac/svc/ACQUIRE.pgc` | 매입 접수 |
| `proc/AUTH_APPROVE.pc` | `app/src/au/svc/AUTH_APPROVE.pgc` | 승인 확정 |
| `proc/ST_MDR.pc` | `app/src/st/svc/ST_MDR.pgc` | MDR 수수료 기표 |
| `proc/SETTLE.pc` | `app/src/st/svc/SETTLE.pgc` | 정산 확정 |
| `proc/RECONCILE.pc` | `app/src/rc/svc/RECONCILE.pgc` | 대사 (CONNECT BY) |
| `proc/CL_DAILY.pc` | `app/src/cl/svc/CL_DAILY.pgc` | 일마감 배치 |
| `proc/PAY_FILEGEN.pc` | `app/src/py/svc/PAY_FILEGEN.pgc` | 지급파일 생성 배치 |
| `plsql/PKG_SETTLE.sql` | (서비스로 인라인) | 정산 PL/SQL 패키지 |
| `plsql/PKG_LEDGER.sql` | (서비스로 인라인) | 원장 기표 PL/SQL 패키지 |

## 왜 DB 는 PostgreSQL 인가 (Oracle 로 되돌리지 않는 이유)

- **To-Be 가 PostgreSQL** 이다(BAIS RFI: Oracle 19c → PostgreSQL 16). DB 이관은 이미
  완료 상태로 두고, Forge 가 다룰 **애플리케이션 이관**(ATMI/임베디드SQL/UXA)에 집중한다.
- 라이선스·재현성: 오픈 스택이라 `docker compose up` 한 번으로 어디서든 실동작.
- 마이그레이션 난이도의 본질은 DB 엔진이 아니라 그 위의 Pro\*C·Tuxedo·XA 계층이며,
  그 난이도는 위 원본들에서 그대로 확인된다.
