2016년 10월 13일 목요일

[Oracle] UTL_HTTP 패키지를 활용한 웹서비스 호출 또는 URL CALL

웹/앱 리뉴얼 프로젝트를 진행 중에 내부에서 처리해야할 프로세스상 로직이 있었는데 오라클(데이터베이스) 단계에서 처리가 곤란하게 되어 외부서비스(웹)의 특정 URL/URI를 호출해야 되는 경우가 생겼다. 구글링으로 검색을 해도 상세히 설명 된 곳이 별로 없다. 잠깐 보게 되면 남겨져 있는 대부분 같은 질문과 대답만 있을 뿐이었다.

#별것도 아닌 것으로 하루 시간을 보낸걸 생각하니 화가 치밀어 오르기도 하면서 나와 같은 사람이 분명 있을 꺼라 생각을 하고 정보를 공유하니 도움이 되시길 바란다. 이보다 여러가지 형태의 호출/호출 후 응답 데이터 활용 등이 있을 수 있으나 해당 포스팅에서는 웹서비스 호출을 하기 위한 준비 정도까지만 공유 하고자 한다.

#설정 후 그 이후 단은 적용하고자 하는 도메인과 요구사항에 따라 달라질 수 있으니 해당 내용에서는 제외 한다.

1. 자 일단 Oracle 에서는 웹서비스 호출 및 메일보내기(?) 등을 사용하기 위해 몇몇의 기본 패키지들을 제공하고 있다.

UTL_URL : URL의 인코딩/디코딩 하는 것을 지원
UTL_TCP : TCP/IP를 사용하여 외부 웹서버와 통신할 수 있는 기능을 제공
 - 참고 : "뇌를 자극하는 오라클 프로그래밍" p576  참고 하시길
UTL_SMTP - 메일보내기

이 포스팅에서 소개할 내용과 실사 내용 보고는 아래의 UTL_HTTP 이다.

UTL_HTTP : Oracle에서 web service 호출을 위한 기능 제공
 - Oracle Help Center : 바로가기


1) UTL_HTTP 패키지를 사용하기 위해서는 우선 ACL(Access Control List - 접근제어목록) 에 사용할 데이터베이스 사용자에게 권한을 부여해야 한다. 아래의 3가지 예제를 통하여 우선 진행 해보자.

 * Example Source
1-1) ACL에 사용하고자 하는 것을 추가 한다.

BEGIN
    DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
              acl => 'my_test_utl_http.xml',
              description => '테스트용 ACL 입니다. ',
              principal => 'ORACLE_USER',  -- ORACLE_USER란 사용자에게 권한 할당
              is_grant => true,
              privilege => 'connect');

      COMMIT;
END;

1-2) ORACLE_USER에게 권한을 할당 .
BEGIN
    DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE (
              acl => 'my_test_utl_http.xml',
              principal => 'ORACLE_USER',  -- ORACLE_USER란 사용자에게 권한 할당
              is_grant => true,
              privilege => 'connect');

      COMMIT;
END;

1-3) 접속할 HOST 정보를 추가
BEGIN
   DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL (
                         acl          => 'my_test_utl_http.xml',              
                         host         => 'www.oracle.com',
                         lower_port => 80,
                         upper_port => 80);
   COMMIT;
END;

2) 추가된 접속 정보가 잘들어 갔는지 SYS AS SYSDBA 권한으로 조회를 확인

select * from DBA_NETWORK_ACLS;
select * from DBA_NETWORK_ACL_PRIVILEGES ;

정상적으로 조회가 된다면 사전 준비가 된것 이다.
이제 간단하게 확인을 해보자.


* Example Source

DECLARE
  req   UTL_HTTP.REQ;
  resp  UTL_HTTP.RESP;
  value VARCHAR2(1024);

BEGIN

  req := UTL_HTTP.BEGIN_REQUEST('http://www.oracle.com');
  UTL_HTTP.SET_HEADER(req, 'User-Agent', 'Mozilla/4.0');
  resp := UTL_HTTP.GET_RESPONSE(req);

  LOOP
    UTL_HTTP.READ_LINE(resp, value, TRUE);
    DBMS_OUTPUT.PUT_LINE(value);
  END LOOP;
  UTL_HTTP.END_RESPONSE(resp);

EXCEPTION WHEN UTL_HTTP.END_OF_BODY THEN
    UTL_HTTP.END_RESPONSE(resp);
END;

결과적으로 해당 웹사이트에 대한 응답에 결과를 출력하게 되므로 HTML 소스의 응답부분을 출력하게 될 것이다. 여러가지 오류사항이 나타날 수 있다. 나 역시 그런 오류들이 당황스럽게 만들기도 하였으니 몇 가지만 공유 하면 다음과 같다.


** 자주보게 되는 오류
* ORA-24247: network access denied by access control list (ACL)
- ACL 설정에 대한 문제 : 사전 준비과정에서 ACL 정보가 잘못들어 간 곳은 없는지 확인하는게 좋다. 가끔 오타가 있는경우가 많을 것이다.

사전 준비 과정에서의 ACL 값을 다 지우고 다시 하고 싶다면 아래의 프로시저를 사용 하면 된다.

exec DBMS_NETWORK_ACL_ADMIN.DROP_ACL(acl => 'my_test_utl_http.xml');

해당 ACL명칭을 사용된 이름을 확인하여 삭제 하면 된다.

* ORA-29273: HTTP request failed
* ORA-06512: at "SYS.UTL_HTTP", line 1130
* ORA-12541: TNS:no listener
* ORA-06512: at line 1

나 처럼 네트워크 라우팅문제 이거나 DNS 문제로 인하여 발생하는 어처구니 없는 상황일 수 있다. 네트워크 담당자에게 확인하거나 본이이 직접 해결하던가 필요 하다. 어찌 되었든 지속적인 접근에 응답이 없어서 그러한 것이다.

왜 안되지 안되지 하면서 허송세월 보내다가 CENTOS 서버 쉘에서

LINUX #] curl -v www.oracle.com

으로 실행해 보니 접속 내역을 보면서 확인 할 수 있다. 확인하다 보니 해당 도메인을 찾지 못하거나 IP정보의 네트워크 상의 라우팅 문제일 수 있으니 말이다. 모두가 쉽게 해결 되길. 좀더 상세한 각 패키지의 기능은 오라클 Help Center 를 활용하시길..




** 참고자료 DBMS_NETWORK_ACL_ADMIN 패키지 중 ACL를 위한 프로시저 설명

① CREATE_ACL 프로시저 - ACL을 생성하는 프로시저
    DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
                 acl         IN VARCHAR2,
                 description IN VARCHAR2,
                 principal   IN VARCHAR2,
                 is_grant    IN BOOLEAN,
                 privilege   IN VARCHAR2,
                 start_date  IN TIMESTAMP WITH TIMEZONE DEFAULT NULL,
                 end_date    IN TIMESTAMP WITH TIMEZONE DEFAULT NULL );

• acl: 생성할 ACL 이름, XML 파일 형태로 생성됨
• description: 설명
• principal: 권한을 부여할 오라클 사용자 명 - 대소문자 구분함 주의 요망
• is_grant: 권한 부여 여부 TRUE/FALSE
• privilege: 기본 ‘connect’ (1-3)에서 ASSIGN_ACL를 DNS가 아닌 IP주소로 사용할 때에는 ‘resolve’ 로 설정 )
• start_date: 시작일자. 기본 값은 NULL.
• end_date: 종료일자. 반드시 시작일자보다 크게 명시해야 하며 기본 값은 NULL


② ADD_PRIVILEGE 프로시저 - 특정 사용자에게 네트워크 접근 권한을 부여
    DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE (
                     acl        IN VARCHAR2,
                     principal  IN VARCHAR2,
                     is_grant   IN BOOLEAN,
                     privilege  IN VARCHAR2,
                     position   IN PLS_INTEGER DEFAULT NULL,
                     start_date IN TIMESTAMP WITH TIMEZONE DEFAULT NULL,
                     end_date   IN TIMESTAMP WITH TIMEZONE DEFAULT NULL );
• acl: ACL 명칭, ①에서 부여한 이름과 동일하게 해야 함
• principal: ①에서 권한을 부여한 오라클 사용자 명 (대소문자 구분)
• is_grant: 권한 부여 여부
• privilege: ‘connect’나 ‘resolve’
• position: ACL의 위치 값으로 생략 가능
• start_date: 시작일자. 기본 값은 NULL.
• end_date: 종료일자. 반드시 시작일자보다 크게 명시해야 하며 기본 값은 NULL


③ ASSIGN_ACL 프로시저 - ACL에 호스트 컴퓨터, 도메인 혹은 IP 등을 할당
    DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL (
                     acl        IN VARCHAR2,
                     host       IN VARCHAR2,
                     lower_port IN PLS_INTEGER DEFAULT NULL
                     upper_port IN PLS_INTEGER DEFAULT NULL);
• acl: ACL 명칭 - ①에서 부여한 이름과 동일하게 해야 함
• host: DNS 명이나 IP 주소. 보통 ‘*.도메임명’를 명시
• lower_port: TCP 포트 하한값 - 기본값 NULL
• upper_port: TCP 포트 상한값 - 기본값 NULL



댓글 없음:

댓글 쓰기

언제 부터 였던가 생각해보니 아르바이트 겸 외부 컨설팅을 의뢰 받고 맥북 프로를 처음 써봤을 때 부터 였던 것 같다. 지금은 거의 대부분의 작업을 맥으로 작업을 하다 보니 윈도우에서만 실행되는 일부 프로그램들 때문과 회사 내부 ERP프로그램이 윈도우 ...