

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 레거시 애플리케이션을 Oracle Pro\*C에서 ECPG로 마이그레이션
<a name="migrate-legacy-applications-from-oracle-pro-c-to-ecpg"></a>

*Sai Parthasaradhi, Mahesh Balumuri, Amazon Web Services*

## 요약
<a name="migrate-legacy-applications-from-oracle-pro-c-to-ecpg-summary"></a>

SQL 코드가 내장된 대부분의 레거시 애플리케이션은 Oracle Pro\*C 프리컴파일러를 사용하여 데이터베이스에 액세스합니다. 이러한 Oracle 데이터베이스를 Amazon Relational Database Service(RDS) for PostgreSQL 또는 Amazon Aurora PostgreSQL-Compatible Edition으로 마이그레이션할 때는 애플리케이션 코드를 PostgreSQL의 사전 컴파일러와 호환되는 형식, 즉 ECPG로 변환해야 합니다. 이 패턴은 PostgreSQL ECPG에서 Oracle Pro\*C 코드를 해당 코드로 변환하는 방법을 설명합니다. 

Pro\*C에 대한 자세한 내용은 [Oracle 설명서](https://docs.oracle.com/cd/E11882_01/appdev.112/e10825/pc_01int.htm#i2415)를 참조하십시오. ECPG에 대한 간략한 소개는 [추가 정보](#migrate-legacy-applications-from-oracle-pro-c-to-ecpg-additional) 섹션을 참조하십시오.

## 사전 조건 및 제한 사항
<a name="migrate-legacy-applications-from-oracle-pro-c-to-ecpg-prereqs"></a>

**사전 조건 **
+ 활성 상태의 AWS 계정
+ Amazon RDS for PostgreSQL 또는 Aurora PostgreSQL-Compatible 데이터베이스
+ 온프레미스에서 실행되는 오라클 데이터베이스

## 도구
<a name="migrate-legacy-applications-from-oracle-pro-c-to-ecpg-tools"></a>
+ 다음 섹션에 나열된 PostgreSql 패키지입니다.
+ [AWS CLI ](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)– AWS Command Line Interface(AWS CLI)는 명령줄 쉘에서 명령을 사용하여 AWS 서비스와 상호 작용하는 오픈 소스 도구입니다. 최소한의 구성으로 AWS CLI 명령을 사용하여 터미널 프로그램에 있는 명령 프롬프트에서 브라우저 기반 AWS Management Console에서 제공되는 것과 동일한 기능을 구현하는 명령을 실행할 수 있습니다.

## 에픽
<a name="migrate-legacy-applications-from-oracle-pro-c-to-ecpg-epics"></a>

### CentOS 또는 RHEL에서 빌드 환경 설정
<a name="set-the-build-environment-on-centos-or-rhel"></a>


| 작업 | 설명 | 필요한 기술 | 
| --- | --- | --- | 
| PostgreSQL 패키지를 설치합니다. | 다음 명령을 사용하여 필요한 PostgreSQL 패키지를 설치합니다.<pre>yum update -y<br />yum install -y yum-utils<br />rpm -ivh https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm<br />dnf -qy module disable postgresql</pre> | 앱 개발자, DevOps 엔지니어 | 
| 헤더 파일 및 라이브러리를 설치합니다. | 다음 명령을 사용하여 헤더 파일 및 라이브러리가 포함된 `postgresql12-devel` 패키지를 설치합니다. 개발 환경과 런타임 환경 모두에 패키지를 설치하여 런타임 환경에서 오류가 발생하지 않도록 하십시오.<pre>dnf -y install postgresql12-devel<br />yum install ncompress zip ghostscript jq unzip wget git -y</pre><br />개발 환경에서만 다음 명령도 실행합니다.<pre>yum install zlib-devel make -y<br />ln -s /usr/pgsql-12/bin/ecpg /usr/bin/</pre> | 앱 개발자, DevOps 엔지니어 | 
| 환경 경로 변수를 구성합니다. | PostgreSQL 클라이언트 라이브러리의 환경 경로를 설정합니다.<pre>export PATH=$PATH:/usr/pgsql-12/bin</pre> | 앱 개발자, DevOps 엔지니어 | 
| 필요에 따라 추가 소프트웨어를 설치합니다. | 필요한 경우 Oracle의 **SQL\*Loader** 대신 **pgLoader**를 설치하십시오.<pre>wget -O /etc/yum.repos.d/pgloader-ccl.repo https://dl.packager.io/srv/opf/pgloader-ccl/master/installer/el/7.repo<br />yum install pgloader-ccl -y<br />ln -s /opt/pgloader-ccl/bin/pgloader /usr/bin/</pre><br />Pro\*C 모듈에서 Java 애플리케이션을 호출하려면 Java를 설치하십시오.<pre>yum install java -y</pre><br />**ant**를 설치하여 자바 코드를 컴파일하십시오.<pre>yum install ant -y</pre> | 앱 개발자, DevOps 엔지니어 | 
| AWS CLI를 설치합니다. | AWS CLI를 설치하면 명령을 실행하여 애플리케이션에서 AWS Secrets Manager 및 Amazon Simple Storage Service(S3)와 같은 AWS 서비스와 상호 작용할 수 있습니다.<pre>cd /tmp/<br />curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"<br />unzip awscliv2.zip<br />./aws/install -i /usr/local/aws-cli -b /usr/local/bin --update</pre> | 앱 개발자, DevOps 엔지니어 | 
| 변활할 프로그램이 표시되어야 합니다. | Pro\*C에서 ECPG로 변환하려는 애플리케이션을 식별하십시오. | 앱 개발자, 앱 소유자 | 

### Pro\*C 코드를 ECPG로 변환
<a name="convert-pro-c-code-to-ecpg"></a>


| 작업 | 설명 | 필요한 기술 | 
| --- | --- | --- | 
| 불필요한 헤더를 삭제합니다. | PostgreSQL에 필요하지 않은 `include ` 헤더(예: `oci.h`, `oratypes` 및 `sqlda`)를 제거합니다. | 앱 소유자, 앱 개발자 | 
| 변수 선언을 업데이트합니다. | 호스트 변수로 사용되는 모든 변수 선언에 `EXEC SQL` 명령문을 추가합니다.<br />애플리케이션에서 다음과 같은 `EXEC SQL VAR` 선언을 제거합니다.<pre>EXEC SQL VAR query IS STRING(2048);</pre> | 앱 개발자, 앱 소유자 | 
| ROWNUM 기능을 업데이트합니다. | PostgreSQL에서는 이 `ROWNUM` 함수를 사용할 수 없습니다. 이 함수를 SQL 쿼리의 `ROW_NUMBER` 윈도우 함수로 바꾸십시오.<br />Pro\*C 코드:<pre>SELECT SUBSTR(RTRIM(FILE_NAME,'.txt'),12) INTO :gcpclFileseq  <br />FROM   (SELECT FILE_NAME <br />FROM  DEMO_FILES_TABLE <br />WHERE FILE_NAME    LIKE '%POC%' <br />ORDER BY FILE_NAME DESC) FL2 <br />WHERE ROWNUM <=1 ORDER BY ROWNUM;</pre><br />ECPG 코드:<pre>SELECT SUBSTR(RTRIM(FILE_NAME,'.txt'),12) INTO :gcpclFileseq  <br />FROM   (SELECT FILE_NAME , ROW_NUMBER() OVER (ORDER BY FILE_NAME DESC) AS ROWNUM<br />FROM  demo_schema.DEMO_FILES_TABLE <br />WHERE FILE_NAME    LIKE '%POC%'<br />ORDER BY FILE_NAME DESC) FL2 <br />WHERE ROWNUM <=1 ORDER BY ROWNUM; </pre> | 앱 개발자, 앱 소유자 | 
| 별칭 변수를 사용하도록 함수 파라미터를 업데이트합니다. | PostgreSQL에서는 함수 파라미터를 호스트 변수로 사용할 수 없습니다. 별칭 변수를 사용하여 덮어씁니다.<br />Pro\*C 코드:<pre>int processData(int referenceId){<br />  EXEC SQL char col_val[100];<br />  EXEC SQL select column_name INTO :col_val from table_name where col=:referenceId;<br />}</pre><br />ECPG 코드:<pre>int processData(int referenceIdParam){<br />  EXEC SQL int referenceId = referenceIdParam;<br />  EXEC SQL char col_val[100];<br />  EXEC SQL select column_name INTO :col_val from table_name where col=:referenceId;<br />}</pre> | 앱 개발자, 앱 소유자 | 
| 구조 유형을 업데이트합니다. | `struct` 유형 변수가 호스트 변수로 사용되는 경우 `typedef`를 사용하여 `EXEC SQL BEGIN` 및 `END` 블록에서 `struct` 유형을 정의합니다. 헤더(`.h`) 파일에 `struct` 유형이 정의된 경우 `EXEC SQL` 명령문을 사용하여 파일을 포함합니다.<br />Pro\*C 코드:<br />헤더 파일(`demo.h`)<pre>struct s_partition_ranges<br />{<br /> char   sc_table_group[31];<br /> char   sc_table_name[31];<br /> char   sc_range_value[10];<br />}; <br />struct s_partition_ranges_ind<br />{<br />  short    ss_table_group;<br />  short    ss_table_name;<br />  short    ss_range_value;<br />}; </pre><br />ECPG 코드:<br />헤더 파일(`demo.h`)<pre>EXEC SQL BEGIN DECLARE SECTION;<br />typedef struct <br />{<br />  char   sc_table_group[31];<br />  char   sc_table_name[31];<br />  char   sc_range_value[10];<br />} s_partition_ranges; <br />typedef struct <br />{<br />  short    ss_table_group;<br />  short    ss_table_name;<br />  short    ss_range_value;<br />} s_partition_ranges_ind; <br />EXEC SQL END DECLARE SECTION;</pre><br />Pro\*C 파일(`demo.pc`)<pre>#include "demo.h"<br />struct s_partition_ranges gc_partition_data[MAX_PART_TABLE] ;<br />struct s_partition_ranges_ind gc_partition_data_ind[MAX_PART_TABLE] ;</pre><br />ECPG 파일(`demo.pc`)<pre>exec sql include "demo.h"<br />EXEC SQL BEGIN DECLARE SECTION;<br />s_partition_ranges gc_partition_data[MAX_PART_TABLE] ;<br />s_partition_ranges_ind gc_partition_data_ind[MAX_PART_TABLE] ;<br />EXEC SQL END DECLARE SECTION;</pre> | 앱 개발자, 앱 소유자 | 
| 커서에서 가져오도록 로직을 수정합니다. | 배열 변수를 사용하여 커서에서 여러 열을 가져오려면 사용할 코드를 `FETCH FORWARD`로 변경하십시오.<br />Pro\*C 코드:<pre>EXEC SQL char  aPoeFiles[MAX_FILES][FILENAME_LENGTH];<br />EXEC SQL FETCH filename_cursor into :aPoeFiles;</pre><br />ECPG 코드:<pre>EXEC SQL char  aPoeFiles[MAX_FILES][FILENAME_LENGTH];<br />EXEC SQL int fetchSize = MAX_FILES;<br />EXEC SQL FETCH FORWARD :fetchSize filename_cursor into :aPoeFiles;</pre> | 앱 개발자, 앱 소유자 | 
| 반환 값이 없는 패키지 호출을 수정합니니다. | 반환 값이 없는 Oracle 패키지 함수는 표시 변수를 사용하여 직접적으로 호출해야 합니다. 애플리케이션에 이름이 같은 함수가 여러 개 포함되어 있거나 알 수 없는 형식 함수로 인해 런타임 오류가 발생하는 경우 값을 데이터 유형으로 타입캐스트합니다.<br />Pro\*C 코드:<pre>void ProcessData (char *data , int id)<br />{        <br />        EXEC SQL EXECUTE<br />               BEGIN<br />                  pkg_demo.process_data (:data, :id);                                                                                    <br />               END;<br />       END-EXEC;<br />}</pre><br />ECPG 코드:<pre>void ProcessData (char *dataParam, int idParam )<br />{<br />        EXEC SQL char *data = dataParam;<br />        EXEC SQL int id = idParam;<br />        EXEC SQL short rowInd;<br />        EXEC SQL short rowInd = 0;<br />        EXEC SQL SELECT pkg_demo.process_data (<br />                       inp_data => :data::text,<br />                       inp_id => :id<br />               ) INTO :rowInd;<br />}</pre> | 앱 개발자, 앱 소유자 | 
| SQL\_CURSOR 변수를 다시 작성하십시오. | `SQL_CURSOR` 변수와 해당 구현을 다시 작성하십시오.<br />Pro\*C 코드:<pre>/* SQL Cursor */<br />SQL_CURSOR      demo_cursor;<br />EXEC SQL ALLOCATE :demo_cursor;<br />EXEC SQL EXECUTE<br />  BEGIN<br />      pkg_demo.get_cursor(     <br />        demo_cur=>:demo_cursor<br />      );<br />  END;<br />END-EXEC;</pre><br />ECPG 코드:<pre>EXEC SQL DECLARE demo_cursor CURSOR FOR SELECT<br />         * from<br />    pkg_demo.open_filename_rc(<br />            demo_cur=>refcursor<br />          ) ;<br />EXEC SQL char open_filename_rcInd[100]; <br /># As the below function returns cursor_name as <br /># return we need to use char[] type as indicator. <br />EXEC SQL SELECT pkg_demo.get_cursor (<br />        demo_cur=>'demo_cursor'<br />    ) INTO :open_filename_rcInd;</pre> | 앱 개발자, 앱 소유자 | 
| 일반적인 마이그레이션 패턴을 적용합니다. | [See the AWS documentation website for more details](http://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/patterns/migrate-legacy-applications-from-oracle-pro-c-to-ecpg.html) | 앱 개발자, 앱 소유자 | 
| 필요한 경우 디버깅을 활성화합니다. | ECPG 프로그램을 디버그 모드에서 실행하려면 기본 함수 블록 내에 다음 명령을 추가합니다.<pre>ECPGdebug(1, stderr); </pre> | 앱 개발자, 앱 소유자 | 

### ECPG 프로그램 컴파일
<a name="compile-ecpg-programs"></a>


| 작업 | 설명 | 필요한 기술 | 
| --- | --- | --- | 
| ECPG용 실행 파일을 생성합니다. | 이름이 지정된 `prog1.pgc` 임베디드 SQL C 소스 파일이 있는 경우 다음 명령 시퀀스를 사용하여 실행 프로그램을 만들 수 있습니다.<pre>ecpg prog1.pgc<br />cc -I/usr/local/pgsql/include -c prog1.c<br />cc -o prog1 prog1.o -L/usr/local/pgsql/lib -lecpg</pre> | 앱 개발자, 앱 소유자 | 
| 컴파일할 메이크 파일을 생성합니다. | 다음 샘플 파일과 같이 make 파일이 생성되어 ECPG 프로그램이 표시되어야 합니다.<pre>CFLAGS ::= $(CFLAGS) -I/usr/pgsql-12/include -g -Wall<br />LDFLAGS ::= $(LDFLAGS) -L/usr/pgsql-12/lib -Wl,-rpath,/usr/pgsql-12/lib<br />LDLIBS ::= $(LDLIBS) -lecpg<br />PROGRAMS = test <br />.PHONY: all clean<br />%.c: %.pgc<br />      ecpg $<<br />all: $(PROGRAMS)<br />clean:<br />    rm -f $(PROGRAMS) $(PROGRAMS:%=%.c) $(PROGRAMS:%=%.o)</pre> | 앱 개발자, 앱 소유자 | 

### 애플리케이션 테스트
<a name="test-the-application"></a>


| 작업 | 설명 | 필요한 기술 | 
| --- | --- | --- | 
| 코드를 테스트합니다. | 변환된 애플리케이션 코드를 테스트하여 제대로 작동하는지 확인하십시오. | 앱 개발자, 앱 소유자, 테스트 엔지니어 | 

## 관련 리소스
<a name="migrate-legacy-applications-from-oracle-pro-c-to-ecpg-resources"></a>
+ [ECPG - C의 임베디드 SQL](https://www.postgresql.org/docs/current/static/ecpg.html)(PostgreSQL 설명서)
+ [오류 처리](https://www.postgresql.org/docs/12/ecpg-errors.html) (PostgreSQL 설명서)
+ [Oracle Pro\*C/C\+\+ 프리컴파일러를 사용하는 이유](https://docs.oracle.com/cd/E11882_01/appdev.112/e10825/pc_01int.htm#i2415)(Oracle 설명서)

## 추가 정보
<a name="migrate-legacy-applications-from-oracle-pro-c-to-ecpg-additional"></a>

PostgreSQL에는 Oracle Pro\*C 프리컴파일러와 동일한 임베디드 SQL 프리컴파일러인 ECPG가 있습니다. ECPG는 SQL 호출을 특수 함수 호출로 대체하여 임베디드 SQL 명령문이 있는 C 프로그램을 표준 C 코드로 변환합니다. 그러면 모든 C 컴파일러 툴 체인을 사용하여 출력 파일을 처리할 수 있습니다.

**입력 및 출력 파일**

ECPG는 명령줄에서 지정하는 각 입력 파일을 해당 C 출력 파일로 변환합니다. 입력 파일 이름에 파일 확장자가 없는 경우에는 .pgc로 간주됩니다. 파일 확장자는 `.c`로 대체되어 출력 파일 이름을 구성합니다. 그러나 `-o` 옵션을 사용하여 기본 출력 파일 이름을 재정의할 수 있습니다.

대시(`-`)를 입력 파일 이름으로 사용하는 경우 `-o` 옵션을 사용하여 재정의하지 않는 한 ECPG는 표준 입력에서 프로그램을 읽고 표준 출력에 씁니다.

**헤더 파일**

PostgreSQL 컴파일러는 사전 처리된 C 코드 파일을 컴파일할 때 PostgreSQL `include` 디렉터리에서 ECPG 헤더 파일을 찾습니다. 따라서 컴파일러가 올바른 디렉터리(예: `-I/usr/local/pgsql/include`)를 가리키도록 `-I` 옵션을 사용해야 할 수도 있습니다.

**Libraries**

임베디드 SQL을 포함한 C 코드를 사용하는 프로그램은 `libecpg` 라이브러리에 연결해야 합니다. 예를 들어 링커 옵션 ` -L/usr/local/pgsql/lib -lecpg`을 사용할 수 있습니다.

변환된 ECPG 애플리케이션은 내장된 SQL `libpq` 라이브러리(`ecpglib`)를 통해 라이브러리의 함수를 직접적으로 호출하고 표준 프런트 엔드/백엔드 프로토콜을 사용하여 PostgreSQL 서버와 통신합니다.