프로세스 메모리 사용량 로그 기록 - 성능 모니터 이용

2017.05.25 11:31

개발한 프로세스에서 메모리 누수(Leak)이 발생된다 예상되면, 메모리 사용량 추적을 통해 메모리 누수 여부를 검증해야 합니다. 성능 모니터를 이용하면 프로세스의 메모리 사용량을 추적 및 로그 기록할 수 있습니다.


만약, 메모리 누수가 확인된다면, 테스트용 실행파일 등으로, 메모리 누수가 발생할 수 있는 코드의 범위를 줄여가며 반복적으로 테스트 해야 합니다.

만약, 특정 기능 수행 시 메모리 누수가 의심된다면 특정 기능을 반복적으로 실행할 수 있는 테스트 프로그램을 만들어 점검할 코드의 범위를 줄여가며 추적하기 바랍니다.


델파이로 개발된 프로젝트라면 메모리 누수 보고 기능을 켜서 메모리 누수 여부를 확인할 수 있습니다.


프로세스 메모리 사용량 추적

윈도우즈 성능 모니터를 이용해 프로세스가 사용 중인 메모리 사용량을 로그파일로 기록하는 방법을 소개합니다.


모니터링 대상 프로세스 실행

메모리 사용량 추적할 프로세스를 실행합니다. 저는 MemoryLeakTest.exe라는 실행파일을 만들어 실행했습니다.


성능 모니터에서 프로세스 메모리 사용량 기록

성능 모니터를 실행하고, 성능 > 데이터 수집기 집합 > 사용자 정의 메뉴를 선택합니다.


목록 창에서 우측 마우스를 누르고, 새로 만들기 > 데이터 수집기 집합 메뉴를 선택합니다.


이름을 지정하고, 수동으로 만들기(고급) 항목 선택 합니다.


성능 카운터 항목을 선택합니다.


[추가] 버튼을 누릅니다.

데이터 수집 가격을 지정합니다.


사용 가능한 카운터에서 Process 항목을 펼치고, Working Set 항목을 선택합니다.

인스턴스로는 추적할 프로세스를 선택합니다.(현재 실행된 프로세스 목록이 표시됩니다.)

[추가] 버튼을 눌러 추가합니다.

(Handle Count, Private Bytes 등 추적하고 싶은 카운터들도 함께 선택해도 됩니다.)

(주요 카운터에 대한 설명은 하단 참고링크 참고)


데이터 저장 경로를 지정합니다.



작업을 마칩니다.


추가한 데이터 수집기 집합의 속성에 들어가 로그 형식을 "쉼표로 구분"으로 변경합니다.(로그를 엑셀로 활용할 수 있습니다.)


성능 모니터링을 시작합니다.(데이터 수집기 집합의 속성에서 예약등을 이용해 자동 시작할 수 있습니다.)


로그파일 확인

지정한 경로에 csv 파일이 생성됩니다.


csv 파일을 엑셀로 열고, 데이터를 분석하거나, 차트를 만들어 시각적으로 메모리 사용량(Working Set) 추이를 관찰 할 수 있습니다.


참고링크


저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

험프리.김현수 험프리.김현수 Delphi/C++Builder

[REST API][실습] REST API 클라이언트 개발하기(REST Client 이용)

2017.05.19 18:24

이 글에서는 델파이를 이용해 REST API 서버와 연동하는 클라이언트 기술을 실습합니다.

REST 클라이언트 라이브러리 기반으로 실습합니다.

REST API 엔드포인트 연동


이 글에서는 REST API 서버의 REST API를 분석하고, 클라이언트에 표시 및 입력데이터를 서버에 저장하는 내용을 실습 위주로 진행합니다.

이 글에서는 데이터 처리하는 내용에 집중합니다. 이 글을 참고해 여러분이 만든 멋진 화면과 REST API를 연동하는 기술을 습득하시기 바랍니다.


이 글에 앞서 다음 내용의 이해가 필요합니다. 미리 선행 학습하시기 바랍니다.


    이 글에서는 다음 내용을 다룹니다.

    • REST API 분석
    • [실습] REST API 연동
      • Get
      • GetItem
      • GetItem - 이미지 수신
      • Post / PutItem / DeleteItem
    • 추가 학습할 내용

    REST API 분석

    이 글에서는 아래 링크에서 제작한 도서정보 REST API 서버를 대상으로 분석 및 연동합니다.


    도서정보 REST API 서버에서 제공하는 엔드포인트는 아래와 같습니다. {item}에는 도서정보 아이디로 치환해야 합니다.

     엔드포인트

     역할

      데이터 포맷

     GET http://localhost:8080/books/

     도서정보 목록 조회

     응답: application/json

     GET http://localhost:8080/books/{item}/

     도서정보 상세 조회

     응답: application/json

     GET http://localhost:8080/books/{Item}/photo/

     도서정보 사진 조회

     응답: image/jpg

     POST http://localhost:8080/books/

     도서정보 생성

     요청 : application/json(Body)

     PUT http://localhost:8080/books/{item}/

     도서정보 수정

     요청 : application/json(Body)

     DELETE http://localhost:8080/books/{item}/

     도서정보 삭제 


    REST API 분석은 REST Debugger(실행: Tools > REST Debugger 메뉴)를 이용합니다.

    REST Debugger 상세정보 - http://docwiki.embarcadero.com/RADStudio/en/REST_Debugger_Tool (자동변역)

    [실습] REST API 연동

    실습에서는 도서대여 REST API 서버와 연동하는 클라이언트 프로그램을 제작합니다.


    실습을 위해 도서대여 패키지를 포함한 EMS 서버를 실행합니다.


    사전 준비사항

    프로젝트 생성

    클라이언트 프로그램은 델파이 멀티-디바이스 애플리케이션(Multi-Device Application)으로 진행합니다.


    멀티-디바이스 애플리케이션 프로젝트를 생성(File > New > Multi-Device Application)합니다. 


    프로젝트에 델파이 데이터 모듈을 추가(File > New > Other > Delphi Projects > Delphi Files > Data Module)합니다.


    프로젝트를 저장합니다.(저는 아래와 같은 이름으로 저장했지만 다른 이름으로 저장해도 됩니다.)


    데이터 모듈 이름을 "dmDataAccess"로 변경합니다. 폼 유닛(MobileForm)에서 데이터 모듈 유닛(DataAccessModule)을 사용할 수 있도록 uses 절에 추가합니다.


    화면 구성(폼 디자인)

    아래 그림을 참고해 화면을 구성합니다.

    다음을 참고해 컴포넌트 이름을 지정합니다.

    • 버튼(TButton)
      • btnLoadData : 데이터 로드
      • btnNewData :  신규
      • btnDeleteData : 삭제
      • btnSaveData : 저장
    • 에디트(TEdit)
      • edtTtile : 제목
      • edtAuthor : 저자
      • edtISBN : ISBN
      • edtPrice : 가격
      • edtLink : 관련링크
    • 메모(TMemo)
      • mmoDescription : 설명

    Get

    Get 엔드포인트를 통해 도서정보 목록을 조회합니다.

    REST API 분석

    REST Debugger에서 아래와 같이 입력합니다.

    • Request 탭
      • Method : Get
      • URL : http://localhost:8080
      • Content-type : application/json
    • Parameters 탭
      • Resource : books
    [Send Request] 버튼을 누릅니다.

    위 이미지와 같이 200 : OK 메시지가 Response 영역에 표시되야 합니다.(200이 아닌 응답 상태 코드를 수신한 경우 EMS 서버 실행여부 또는 URL 등을 확인하시기 바랍니다.)


    Response 영역의 Headers 탭과 Body탭을 통해 데이터 수신을 확인합니다.

    JSON 데이터를 확인해, JSON 배열([])로 구성된 속성을 확인해 JSON Root Element에 입력 후 [Apply] 버튼을 클릭(또는 엔터)합니다.


    Tabular Data 탭에 배열의 데이터가 테이블 형식으로 표시됩니다.


    [Copy Components] 버튼을 눌러 분석한 데이터를 클립보드로 복사합니다.(이 컴포넌트는 개발에 직접 사용합니다.)


    REST API 연동 구현

    데이터 모듈에 붙여넣기(Ctrl + V) 후 아래 그림을 참고해 이름을 변경합니다.


    각 컴포넌트의 역할과 주요 속성

    • TRESTClient - 서버 정보 설정
      • BaseURL : 서버 기본 URL
    • TRESTRequest - 요청할 정보 설정 및 요청 작업 수행
      • Client : TRESTClient 지정
      • Method : 요청 시 HTTP 메소드 종류
      • Resource : REST API 리소스 지정(URI에서 BaseURL 제외한 영역), 파라메터는 중괄호({})로 지정
      • Params : Resource에 포함된 파라메터 값 정
      • Response : 응답 객체(TRESTResponse) 지정
    • TRESTResponse - 요청의 응답 정보 보관
      • Content : 응답받은 데이터(string)
      • RootElement : 응답 데이터 중 필요한 항목 지정
    • TRESTResponseDataSetAdapter - 응답 데이터를 데이터셋으로 변환
      • Response : 변환 대상 응답데이터
      • Dataset : 변환한 데이터를 기록할 데이터 셋(TDataSet을 상속받은 메모리 테이블, TFDMemTable 또는 TClientDataSet 등)
      • RootElement : 응답 데이터 중 변환할 항목 지정
    • TFDMemTable - 메모리 테이블

    reqList 컴포넌트 팝업메뉴에서 Execute 메뉴를 눌러 연결을 확인하고 데이터를 가져옵니다.

    이 작업은 REST API 서버의 데이터를 받아 메모리테이블(TFDMemTable)에 데이터를 로드합니다. 이 데이터를 기반으로 메모리 테이블의 필드 정보를 표시하고, UI 컨트롤에 데이터를 표시합니다. 델파이에서 프로젝트를 새로 열었다면, 위 작업을 다시 시도해 데이터를 메모리 테이블에 로드해야 합니다.

    폼의 [데이터 로드] 버튼 클릭 이벤트에 아래 코드를 구현합니다.

      dmDataAccess.reqList.Execute;


    도서목록 데이터를 그리드에 표시하기 위해 라이브 바인딩 디자이너 표시(View > Tool Windows > LiveBindings Designer) 후 아래 그림을 참고해 데이터와 UI컨트롤을 바인딩 합니다.


    프로젝트를 실행하고, [데이터 로드] 버튼을 눌러 그리드에 정보가 표시되는 것을 확인합니다.

    GetItem

    GetItem 엔드포인트를 통해 도서정보 목록을 조회합니다.

    REST API 분석

    REST Debugger에서 아래와 같이 입력합니다.

    • Request 탭
      • Method : Get
      • URL : http://localhost:8080
      • Content-type : application/json
    • Parameters 탭
      • Resource : books/{item}/
      • Request parameters : item 항목에 도서정보 아이디 값 입력
    [Send Request] 버튼을 누릅니다.

    응답 데이터 확인 후 JSON Root Element에 "book" 입력 후 [Apply] 버튼을 누르고, Tabular Data 탭에서 데이터 표시를 확인합니다.

    [Copy Components] 버튼을 누릅니다.

    REST API 연동 구현

    데이터 모듈에 붙여넣기 후 아래와 같이 이름을 변경합니다.


     TRESTClient는 재사용합니다. RESTClient2 컴포넌트를 제거합니다. reqDetail.Client 항목을 RESTClient1으로 지정합니다.


    reqDetail 컴포넌트 팝업메뉴에서 Execute 메뉴를 눌러 데이터를 가져옵니다.


    폼에서 라이브 바인딩 디자이너를 표시하고, 아래 그림을 참고해 바인딩합니다.


    private 영역에 아래 변수와 메소드 추가 후 자동 완성(Shift + Ctrl + C)으로 구현부를 생성합니다.

      private
        FSelectedSeq: Integer;
        procedure RequestDetail(ASeq: Integer);
        procedure LoadPhoto(ASeq: Integer);
        procedure ClearControls;


    그리드의 OnSelChanged 이벤트(그리드 셀 변경)를 추가후 아래 코드를 구현합니다.

    procedure TForm1.Grid1SelChanged(Sender: TObject);
    var
      Seq: Integer;
    begin
      if dmDataAccess.memBookList.RecordCount = 0 then
        Exit;
    
      Seq := dmDataAccess.memBookList.FieldByName('BOOK_SEQ').AsInteger;
      RequestDetail(Seq);
    end;
    
    procedure TForm1.ClearControls;
    begin
      dmDataAccess.memBookDetail.EmptyDataSet;
      ImageControl1.Bitmap.Assign(nil);
    end;
    
    procedure TForm1.RequestDetail(ASeq: Integer);
    begin
      FSelectedSeq := ASeq;
    
      ClearControls;
    
      dmDataAccess.reqDetail.Params.ParameterByName('item').Value := ASeq.ToString;
      BindSourceDB2.DataSource.Enabled := False;
      dmDataAccess.reqDetail.ExecuteAsync(procedure
      begin
        BindSourceDB2.DataSource.Enabled := True;
      end);
    
      LoadPhoto(ASeq);
    end;
    
    procedure TForm1.LoadPhoto(ASeq: Integer);
    begin
    end;

    LoadPhoto 메소드는 아래에서 구현합니다.

    GetItem - 이미지 수신

    REST API 연동 구현

    이미지 수신, 생성, 수정, 삭제에 공통으로 사용할 컴포넌트를 데이터 모듈에 추가합니다.


    RESTRequest의 Client 항목을 RESTClient1으로 Reponse 항목을 RESTResponse로 지정합니다.


    LoadPhoto 메소드에 아래와 같이 구현합니다.
    procedure TForm1.LoadPhoto(ASeq: Integer);
    var
      Stream: TMemoryStream;
    begin
      dmDataAccess.RESTRequest.Method := TRESTRequestMethod.rmGET;
      dmDataAccess.RESTRequest.Resource := '/books/{item}/photo/';
      dmDataAccess.RESTRequest.Params.ParameterByName('item').Value := ASeq.ToString;
      dmDataAccess.RESTRequest.ExecuteAsync(procedure
        begin
          if dmDataAccess.RESTResponse.StatusCode = 404 then
            Exit;
          Stream := TMemoryStream.Create;
          try
            Stream.WriteData(dmDataAccess.RESTResponse.RawBytes, dmDataAccess.RESTResponse.ContentLength);
            ImageControl1.Bitmap.LoadFromStream(Stream);
          finally
            Stream.Free;
          end;
        end);
    
    end;
    프로젝트를 실행하고, 그리드를 변경해 상세 데이터 및 이미지 표현을 확인합니다.

    Post / PutItem / DeleteItem

    신규, 저장, 삭제 기능을 구현합니다.

    REST API 연동 구현

    데이터 모듈에서 데이터셋의 데이터를 JSON으로 반환하는 메소드를 작성합니다. 이 메소드는 Post, PutItem 엔드포인트 호출 시 사용합니다.


    데이터 모듈의 uses 절에 "System.JSON, System.JSON.Writers"을 추가합니다.


    아래 코드를 참고해, GetBookData 메소드를 정의하고, 구현합니다.

    function TdmDataAccess.GetBookData: TJSONObject;
    var
      Writer: TJsonObjectWriter;
    begin
      Writer := TJsonObjectWriter.Create(False);
      try
        Writer.WriteStartObject;  // start resource
        Writer.WritePropertyName('book');
    
        Writer.WriteStartObject;  // start item
        Writer.WritePropertyName('BOOK_TITLE');
        Writer.WriteValue(memBookDetail.FieldByName('BOOK_TITLE').AsString);
    
        Writer.WritePropertyName('BOOK_ISBN');
        Writer.WriteValue(memBookDetail.FieldByName('BOOK_ISBN').AsString);
    
        Writer.WritePropertyName('BOOK_AUTHOR');
        Writer.WriteValue(memBookDetail.FieldByName('BOOK_AUTHOR').AsString);
    
        Writer.WritePropertyName('BOOK_PRICE');
        Writer.WriteValue(memBookDetail.FieldByName('BOOK_PRICE').AsString);
    
        Writer.WritePropertyName('BOOK_LINK');
        Writer.WriteValue(memBookDetail.FieldByName('BOOK_LINK').AsString);
    
        Writer.WritePropertyName('BOOK_DESCRIPTION');
        Writer.WriteValue(memBookDetail.FieldByName('BOOK_DESCRIPTION').AsString);
    
        Writer.WriteEndObject;  // end item
        Writer.WriteEndObject;  // end resource
    
        Result := Writer.JSON as TJSONObject;
      finally
        Writer.Free;
      end;
    end;

    [신규], [삭제], [저장] 버튼의 이벤트에 아래 코드를 작성합니다.

    procedure TForm1.btnNewDataClick(Sender: TObject);
    begin
      FSelectedSeq := -1;
      ClearControls;
    end;
    
    procedure TForm1.btnSaveDataClick(Sender: TObject);
    var
      Data: TJSONObject;
    begin
      if FSelectedSeq = -1 then
      begin
        dmDataAccess.RESTRequest.Method := TRESTRequestMethod.rmPOST;
        dmDataAccess.RESTRequest.Resource := '/books/';
      end
      else
      begin
        dmDataAccess.RESTRequest.Method := TRESTRequestMethod.rmPUT;
        dmDataAccess.RESTRequest.Resource := '/books/{item}/';
        dmDataAccess.RESTRequest.Params.ParameterByName('item').Value := FSelectedSeq.ToString;
      end;
      dmDataAccess.RESTRequest.ClearBody;
      Data := dmDataAccess.GetBookData;
      dmDataAccess.RESTRequest.Body.Add(Data);
      dmDataAccess.RESTRequest.Execute;
    
      ShowMessage('저장');
    end;
    
    procedure TForm1.btnDeleteDataClick(Sender: TObject);
    begin
      dmDataAccess.RESTRequest.Method := TRESTRequestMethod.rmDELETE;
      dmDataAccess.RESTRequest.Resource := '/books/{item}/';
      dmDataAccess.RESTRequest.Params.ParameterByName('item').Value := FSelectedSeq.ToString;
      dmDataAccess.RESTRequest.Execute;
    
      ShowMessage('삭제');
    end;

    위 코드와 같이 단순한 요청, 응답의 경우 컴포넌트를 재사용 하는 것도 좋은 방법입니다.

    추가 학습할 내용










    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 Delphi/C++Builder

    [REST API][실습] REST API 서버 개발하기(엔드포인트 구현, RAD 서버 이용)

    2017.05.17 11:31

    이 글에서는 델파이를 이용해 REST API 엔드포인트를 제공하는 서버 제작 기술을 학습합니다.

    RAD 서버의 EMS 패키지 프로젝트로 진행합니다.

    REST API 엔드포인트

    리소스에 HTTP 메소드 요청 시 처리하도록 구현해 놓은 것을 REST API 엔드포인트라고합니다.


    REST는 GET, POST, PUT, DELETE 4개의 HTTP 메소드 지원을 원칙으로하며, 그 중 지원할 HTTP 메소드를 지정 및 구현해 REST API를 제공합니다. 즉 리소스에 따라 필요한 HTTP 메소드에 한해 엔드포인트를 제공할 수 있습니다.


    이 글에서는 RAD 서버를 이용해 리소스를 생성하고, 엔드포인트를 작성하는 실습을 진행합니다.

    실습의 주제는 도서정보를 제공하는 REST API를 개발합니다.


    실습에서 사용하는 데이터베이스는 도서대여 프로그램 만들기에서 사용한 데이터베이스를 사용합니다. 다음 링크의 참고 링크에서 다운로드 받으시기 바랍니다.


    이 글에 앞서 다음 내용을 이해하고 있어야 합니다. 미리 선행 학습하시기 바랍니다.


    이 글에서는 다음 내용을 다룹니다.

    • EMS 패키지 프로젝트 시작하기
    • [실습] REST API 엔드포인트 개발하기
      • Get / GetItem
        • REST Debugger 소개
      • Post / PutItem / DeleteItem
      • GetItem - 이미지 제공
    • 추가 학습할 내용

    EMS 패키지 프로젝트 시작하기

    EMS 패키지 프로젝트를 이용해 REST API 리소스와 엔드포인트를 개발할 수 있습니다.


    EMS 패키지를 생성하고, 실행하는 내용은 다음 링크를 통해 선행 학습하시기 바랍니다.

    EMS 패키지 프로젝트 생성

    "books" 이름으로 리소스 이름을 지정하고 파일유형으로 Data Module을 선택 합니다.


    엔드포인트를 모두 선택 합니다.


    프로젝트를 생성하면 아래와 같은 코드가 자동 생성됩니다.


    [ResourceName('books')]

    리소스 이름을 지정하는 특성 구문으로, 아래의 클래스(TBooksResource1)의 리소스 이름을 지정합니다.

    이 이름은 URI에 사용되며, URI(http://localhost:8080/books/) 요청 시 리소스 이름이 지정된 클래스의 엔드포인트 프로시저를 실행합니다. 이 이름은 코드 상에서 수정할 수 있습니다.


    [ResourceSuffix('{item}')]

    리소스 뒤에 붙는 리소스접미사를 정의하는 특성(Attribute) 구문입니다.

    URI(http://localhost:8080/books/100/)에서 리소스 이름 뒤의 영역을 지정합니다.

    중괄호({..})로 정의된 항목은 파라메터로 지정되어, 코드로 읽어 올 수 있습니다.


    예를들어 "http://localhost:8080/books/100/"으로 호출하는 경우, "100"이 접미사이며, 중괄호로 파라메터로 지정된 경우 다음 코드로 값을 가져올 수 있습니다.

    ARequest.Params.Values['item'] // 100

    리소스접미사는 여러 단계로 정의할 수 있습니다. 

    [ResourceSuffix('{item}/photo/')]
    procedure GetItemPhoto(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [ResourceSuffix('{item}/{subitem}/')]
    procedure GetItemSub(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);


    HTTP 메소드 프로시저

    EMS 패키지에서는 Get, GetItem, Post, PutItem, DeleteItem 총 5개의 엔드포인트를 제공합니다.

     엔드포인트

     HTTP 메소드

     리소스 접미사

     Get

     GET

     

     GetItem

     GET

     {item}

     Post

     POST

     

     PutItem

     PUT

     {item}

     DeleteItem

     DELETE

     {item}


    위 표와 같이, 엔드포인트는 HTTP 메소드, 리소스 접미사와 매핑됩니다. 

    Get 을 예로 들면, GET으로 리소스에 요청하면 엔드포인트 Get 프로시저가 호출되고, {item}이 포함되어 GET으로 요청하면 GetItem 프로시저가 호출됩니다.


    각 엔드포인트의 프로시저는 엔드포인트 이름으로 시작되도록 정의해야합니다. 만약, 같은 엔드포인트가 프로시저가 2개이상 구현된 경우 실행 시 오류가 발생합니다.


    [실습] REST API 엔드포인트 개발하기

    이 장에서는 엔드포인트 별로 기능을 구현하고 실습하는 방법을 안내합니다.

    실습에서는 도서대여 프로그램의 데이터베이스를 사용 합니다. 데이터 포맷으로는 JSON을 사용합니다.


    사전 준비사항

    다음 디렉토리 구조로 진행합니다.

    도서대여 프로그램 데이터베이스 파일을 DB 디렉토리에 저장합니다.


    위에서 생성한 EMS 패키지 프로젝트 Source 디렉토리에 저장합니다.


    프로젝트 옵션에서 Output 디렉토리를 지정합니다.


    BookResource 데이터 모듈에 아래와 같이 TFDConnection, TFDQuery 컴포넌트를 추가하고 이름을 변경합니다.


    conBookRental(TFDConnection)의 OnBeforeConnect 이벤트 핸들러 생성 후 아래 코드(데이터베이스 파일 경로를 지정)를 추가합니다. uses 절에 System.IOUtils를 추가합니다.

    procedure TBooksResource1.conBookRentalBeforeConnect(Sender: TObject);
    var
      Path: string;
    begin
      Path := TPath.GetFullPath('..\DB\BOOKRENTAL.IB');
      if not TFile.Exists(Path) then
      begin
        raise Exception.Create('Not found database.');
      end;
    
      conBookRental.Params.Values['Database'] := Path;
    end;


    Get / GetItem

    리소스에 GET 메소드로 요청하면 Get 또는 GetItem(접미사가 있을 경우)이 호출됩니다. GET 메소드는 조회 역할을 하면 각 엔드포인트는 다음 역할을 구현합니다.

    • Get - 리소스의 목록 정보 조회
    • GetItem - 리소스의 상세 정보 조회

    Get - 리소스 목록

    Get 엔드포인트는 리소스 목록을 조회하는 역할을 합니다. 실습에서는 도서정보 리소스를 구현하므로, 도서 정보 목록을 제공하도록 구현합니다.


    GET http://localhost:8080/books/

    {
      "books":
      {
        "total":6,
        "book":
        [
          {
            "BOOK_SEQ":15,
            "BOOK_TITLE":"델파이 Begin...End",
            "BOOK_AUTHOR":"김원경"
          },      
          {
            "BOOK_SEQ":16,
            "BOOK_TITLE":"한 번에 개발하는 안드로이드 iOS앱 with 델파이. 1편",
            "BOOK_AUTHOR":"김원경 , 김현수, 오상현"
          }
        ]
      }
    }

    Get 엔드포인트에 아래와 같이 구현합니다. JSON 데이터 작성은 TJsonObjectWriter를 이용했습니다. 다른 JSON 라이브러리를 사용해 작성해도 무관합니다.

    procedure TBooksResource1.Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    const
      SQL_LIST ='SELECT BOOK_SEQ, BOOK_TITLE, BOOK_AUTHOR, BOOK_PRICE FROM BOOK';
    var
      Writer: TJsonObjectWriter;
    begin
      qryBook.Close;
      qryBook.SQL.Text := SQL_LIST;
      qryBook.Open;
    
      Writer := TJsonObjectWriter.Create;
      try
        Writer.WriteStartObject; // start resource
        Writer.WritePropertyName('books');
    
        Writer.WriteStartObject; // start item
        Writer.WritePropertyName('total');
        Writer.WriteValue(qryBook.RecordCount);
    
        Writer.WritePropertyName('book');
        Writer.WriteStartArray;
    
        qryBook.First;
        while not qryBook.Eof do
        begin
          Writer.WriteStartObject;
          Writer.WritePropertyName('BOOK_SEQ');
          Writer.WriteValue(qryBook.FieldByName('BOOK_SEQ').AsInteger);
    
          Writer.WritePropertyName('BOOK_TITLE');
          Writer.WriteValue(qryBook.FieldByName('BOOK_TITLE').AsString);
    
          Writer.WritePropertyName('BOOK_AUTHOR');
          Writer.WriteValue(qryBook.FieldByName('BOOK_AUTHOR').AsString);
    
          Writer.WritePropertyName('BOOK_PRICE');
          Writer.WriteValue(qryBook.FieldByName('BOOK_PRICE').AsString);
    
          Writer.WriteEndObject;
          qryBook.Next;
        end;
    
        Writer.WriteEndArray;
    
        Writer.WriteEndObject;  // end item
        Writer.WriteEndObject;  // end resource
    
        AResponse.Body.SetValue(Writer.JSON as TJSONValue, True);
      except
        Writer.Free;
        raise;
      end;
    end;

    구현을 마치면, 프로젝트를 실행하고 웹브라우저에서 "http://localhost:8080/books/"를 입력해 JSON 문자열이 화면에 표시되는 것을 확인합니다.


    GetItem - 리소스 상세

    GetItem 엔드포인트는 특정 도서의 상세 정보를 제공하도록 구현합니다.


    GET http://localhost:8080/books/{item}/

    {
      "book":
      {
        "BOOK_SEQ":15,
        "BOOK_TITLE":"델파이 Begin...End",
        "BOOK_ISBN":"9788996251613",
        "BOOK_AUTHOR":"김원경",
        "BOOK_PRICE":"28000",
        "BOOK_LINK":"http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788996251613&orderClick=LAG&Kc=SETLBkserp1_5",
        "BOOK_DESCRIPTION":"델파이의 시작부터 끝까지 파헤치다!
    ... (생략)"
      }
    }

    다음과 같이 구현합니다.

    procedure TBooksResource1.GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    const
      SQL_ITEM_INFO = 'SELECT ' +
                        'BOOK_SEQ, BOOK_TITLE, BOOK_ISBN, BOOK_AUTHOR, BOOK_PRICE, ' +
                        'BOOK_LINK, BOOK_DESCRIPTION ' +
                      'FROM BOOK WHERE BOOK_SEQ = :BOOK_SEQ';
    
    var
      BOOK_SEQ: string;
      Writer: TJsonObjectWriter;
    begin
      BOOK_SEQ := ARequest.Params.Values['item'];
      // Sample code
      qryBook.Close;
      qryBook.SQL.Text := SQL_ITEM_INFO;
      qryBook.ParamByName('BOOK_SEQ').AsString := BOOK_SEQ;
      qryBook.Open;
    
      if qryBook.RecordCount = 0 then
        AResponse.RaiseNotFound('Not found', '''' + BOOK_SEQ + ''' is not found');
    
      Writer := TJsonObjectWriter.Create;
      try
        Writer.WriteStartObject;  // start resource
        Writer.WritePropertyName('book');
    
        Writer.WriteStartObject;  // start item
        Writer.WritePropertyName('BOOK_SEQ');
        Writer.WriteValue(qryBook.FieldByName('BOOK_SEQ').AsInteger);
    
        Writer.WritePropertyName('BOOK_TITLE');
        Writer.WriteValue(qryBook.FieldByName('BOOK_TITLE').AsString);
    
        Writer.WritePropertyName('BOOK_ISBN');
        Writer.WriteValue(qryBook.FieldByName('BOOK_ISBN').AsString);
    
        Writer.WritePropertyName('BOOK_AUTHOR');
        Writer.WriteValue(qryBook.FieldByName('BOOK_AUTHOR').AsString);
    
        Writer.WritePropertyName('BOOK_PRICE');
        Writer.WriteValue(qryBook.FieldByName('BOOK_PRICE').AsString);
    
        Writer.WritePropertyName('BOOK_LINK');
        Writer.WriteValue(qryBook.FieldByName('BOOK_LINK').AsString);
    
        Writer.WritePropertyName('BOOK_DESCRIPTION');
        Writer.WriteValue(qryBook.FieldByName('BOOK_DESCRIPTION').AsString);
    
        Writer.WriteEndObject;  // end item
        Writer.WriteEndObject;  // end resource
    
        AResponse.Body.SetValue(Writer.JSON as TJSONValue, True);
      except
        Writer.Free;
        raise;
      end;
    end;

    구현을 마치고, 프로젝트를 실행하고, 웹브라우저에 "http://localhost:8080/books/{item}/"({item}은 목록의 BOOK_SEQ로 치환합니다.) 입력해 결과를 확인합니다.

    RESTDebugger - REST API 분석도구

    GET 메소드의 경우 웹브라우저로 손쉽게 테스트 해볼 수 있습니다. 테스트 하기 어려운 POST, PUT, DELETE 메소들은 RESTDebugger를 이용해 테스트 할 수 있습니다.


    RESTDebugger는 Tools > REST Debugger 메뉴를 사용해 실행합니다.

    Request 탭의 Method(HTTP 메소드), URL, Conentt-type, Custom body 등을 지정 후


    Parameters 탭에서 Resource, Request Parameters 항목을 지정 해 [Send Reuqest] 버튼을 눌러 요청합니다.

    Resource 항목의 경우 {item}과 같이 중괄호로 지정한 항목이 자동으로 파라메터에 추가됩니다.


    응답은 Headers와 Body 탭에 정보가 표시됩니다.



    자세한 사용법은 다음 링크를 참고하시기 바랍니다.


    Post / PutItem / DeleteItem

    리소스를 생성, 수정, 삭제합니다. 생성과 수정에 필요한 정보는 요청 시 Custom Body영역에 JSON 포맷으로 전달하도록 구현합니다.

    Post - 리소스 생성

    Post 엔드포인트는 도서정보를 생성하도록 구현합니다. 도서에 대한 정보는 요청(Request)의 Custom Body에 담긴JSON 데이터를 이용합니다.

    POST http://localhost:8080/books/
    Custom Body

    {
      "book":
      {
        "BOOK_TITLE":"테스트",
        "BOOK_ISBN":"1234567890123",
        "BOOK_AUTHOR":"홍길동",
        "BOOK_PRICE":"10000",
        "BOOK_LINK":"",
        "BOOK_DESCRIPTION":"12345."
      }
    }


    다음과 같이 구현합니다.

    procedure TBooksResource1.Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    const
      SQL_ITEM_INSERT = 'INSERT INTO BOOK(BOOK_TITLE, BOOK_ISBN, BOOK_AUTHOR, BOOK_PRICE, BOOK_LINK, BOOK_DESCRIPTION)' +
                        '  VALUES (:BOOK_TITLE, :BOOK_ISBN, :BOOK_AUTHOR, :BOOK_PRICE, :BOOK_LINK, :BOOK_DESCRIPTION)';
    
    var
      Title, Author, Price, ISBN, Link, Desc: string;
      Json: TJSONValue;
    begin
      JSON := ARequest.Body.GetValue;
    
      Title := JSON.GetValue<string>('book.BOOK_TITLE');
      ISBN := JSON.GetValue<string>('book.BOOK_ISBN');
      Author := JSON.GetValue<string>('book.BOOK_AUTHOR');
      Price := JSON.GetValue<string>('book.BOOK_PRICE');
      Link := JSON.GetValue<string>('book.BOOK_LINK');
      Desc := JSON.GetValue<string>('book.BOOK_DESCRIPTION');
      qryBook.Close;
      qryBook.SQL.Text := SQL_ITEM_INSERT;
      qryBook.ParamByName('BOOK_TITLE').AsString := Title;
      qryBook.ParamByName('BOOK_ISBN').AsString := ISBN;
      qryBook.ParamByName('BOOK_AUTHOR').AsString := Author;
      qryBook.ParamByName('BOOK_PRICE').AsString := Price;
      qryBook.ParamByName('BOOK_LINK').AsString := Link;
      qryBook.ParamByName('BOOK_DESCRIPTION').AsString := Desc;
      qryBook.ExecSQL;
    end;


    구현을 마치고, 프로젝트를 실행합니다. REST Debugger에서 아래와 같이 정보 입력해 테스트 합니다. 요청 후 도서 목록(http://localhost:8080/books/)에서 추가된 것을 확인합니다.


    현재(2017.05) REST Debugger의 Custom Body가 유니코드를 지원하지 않는 버그가 있습니다.(한글을 입력 후 요청 시 캐릭터셋이 맞지 않는 오류가 EMS 패키지에서 발생합니다.)


    조치방법

    1번안 - REST Debugger 소스코드를 수정합니다.

    • C:\Program Files (x86)\Embarcadero\Studio\19.0\source\data\rest\restdebugger\RESTDebugger.dpr(10.2 도쿄 기준) 프로젝트 열기
    • uMain_frm.pas의 762번째 줄을 아래와 같이 수정
      •   memo_RequestBody.Lines.SaveToStream(FRESTParams.CustomBody, TEncoding.UTF8);
    • 컴파일(Project > Options > Delphi Compoiler > Output Directory를 접근 권한이 있는 곳으로 변경)


    2번안 - 아래 RESTDebugger 실행파일을 다운로드 후 테스트 합니다.

    RESTDebugger.zip


    PutItem - 리소스 수정

    PutItem 엔드포인트는 특정한 도서정보를 수정하도록 구현합니다. 도서의 Id는 리소스 접미사를 이용해 파악합니다. 도서에 대한 정보는 요청(Request)의 Custom Body에 담긴JSON 데이터를 이용합니다.

    PUT http://localhost:8080/books/{item}/ - {item}은 유효한 도서일련번호로 변경할 것
    Custom Body

    {
      "book":
      {
        "BOOK_TITLE":"테스트 수정",
        "BOOK_ISBN":"1234567890123",
        "BOOK_AUTHOR":"홍길동",
        "BOOK_PRICE":"10000",
        "BOOK_LINK":"",
        "BOOK_DESCRIPTION":"12345."
      }
    }


    다음과 같이 구현합니다.

    procedure TBooksResource1.PutItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    const
      SQL_ITEM_UPDATE = 'UPDATE BOOK SET ' +
                        '  BOOK_TITLE = :BOOK_TITLE,' +
                        '  BOOK_ISBN = :BOOK_ISBN, ' +
                        '  BOOK_AUTHOR = :BOOK_AUTHOR,' +
                        '  BOOK_PRICE = :BOOK_PRICE,' +
                        '  BOOK_LINK = :BOOK_LINK, ' +
                        '  BOOK_DESCRIPTION = :BOOK_DESCRIPTION ' +
                        ' WHERE ' +
                        '  BOOK_SEQ = :BOOK_SEQ';
    
    var
      BOOK_SEQ: string;
      Title, Author, Price, ISBN, Link, Desc: string;
      Json: TJSONValue;
    begin
      BOOK_SEQ := ARequest.Params.Values['item'];
      JSON := ARequest.Body.GetValue;
    
      Title := JSON.GetValue<string>('book.BOOK_TITLE');
      ISBN := JSON.GetValue<string>('book.BOOK_ISBN');
      Author := JSON.GetValue<string>('book.BOOK_AUTHOR');
      Price := JSON.GetValue<string>('book.BOOK_PRICE');
      Link := JSON.GetValue<string>('book.BOOK_LINK');
      Desc := JSON.GetValue<string>('book.BOOK_DESCRIPTION');
      qryBook.Close;
      qryBook.SQL.Text := SQL_ITEM_UPDATE;
      qryBook.ParamByName('BOOK_TITLE').AsString := Title;
      qryBook.ParamByName('BOOK_ISBN').AsString := ISBN;
      qryBook.ParamByName('BOOK_AUTHOR').AsString := Author;
      qryBook.ParamByName('BOOK_PRICE').AsString := Price;
      qryBook.ParamByName('BOOK_LINK').AsString := Link;
      qryBook.ParamByName('BOOK_DESCRIPTION').AsString := Desc;
      qryBook.ParamByName('BOOK_SEQ').AsString := BOOK_SEQ;
      qryBook.ExecSQL;
    
      if qryBook.RowsAffected = 0 then
        AResponse.RaiseNotFound('Not found', '''' + BOOK_SEQ + ''' is not found');
    end;


    구현을 마치고, 프로젝트를 실행합니다. REST Debugger에서 아래와 같이 정보 입력해 테스트 합니다. 요청 후 도서 목록(http://localhost:8080/books/)에서 수정된 것을 확인합니다.


    DeleteItem - 리소스 삭제

    DeleteItem 엔드포인트는 특정 도서정보를 삭제하도록 구현합니다. 도서의 Id는 리소스 접미사를 이용해 파악합니다. 

    DELETE http://localhost:8080/books/{item}/ - {item}은 유효한 도서일련번호로 변경할 것

    다음과 같이 구현합니다.

    procedure TBooksResource1.DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    const
      SQL_ITEM_DELETE ='DELETE FROM BOOK WHERE BOOK_SEQ = :BOOK_SEQ';
    
    var
      BOOK_SEQ: string;
    begin
      BOOK_SEQ := ARequest.Params.Values['item'];
    
      qryBook.Close;
      qryBook.SQL.Text := SQL_ITEM_DELETE;
      qryBook.ParamByName('BOOK_SEQ').AsString := BOOK_SEQ;
      qryBook.ExecSQL;
    
      if qryBook.RowsAffected = 0 then
        AResponse.RaiseNotFound('Not found', '''' + BOOK_SEQ + ''' is not found');
    end;


    구현을 마치고, 프로젝트를 실행합니다. REST Debugger에서 아래와 같이 정보 입력해 테스트 합니다. 요청 후 도서 목록(http://localhost:8080/books/)에서 삭제된 것을 확인합니다.


    GetItem - 이미지 제공

    도서정보의 경우 이미지를 제공합니다. 이미지 제공은 상세 정보 하위 "photo" 리소스를 추가해 구현합니다.


    GET http://localhost:8080/books/{item}/photo/ - {item}은 유효한 도서일련번호로 변경할 것

    아래 코드를 참고해 하위 리소스 엔드포인트를 추가합니다.

    [ResourceSuffix('{item}/photo/')]
    procedure GetItemPhoto(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);

    다음과 같이 구현합니다. 

    procedure TBooksResource1.GetItemPhoto(const AContext: TEndpointContext;
      const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    const
      SQL_ITEM_IMAGE ='SELECT BOOK_IMAGE FROM BOOK WHERE BOOK_SEQ = :BOOK_SEQ';
    var
      BOOK_SEQ: string;
      Stream: TMemoryStream;
    begin
      BOOK_SEQ := ARequest.Params.Values['item'];
    
      Stream := TMemoryStream.Create;
      try
        qryBook.Close;
        qryBook.SQL.Text := SQL_ITEM_IMAGE;
        qryBook.ParamByName('BOOK_SEQ').AsString := BOOK_SEQ;
        qryBook.Open;
    
        if qryBook.RecordCount = 0 then
          AResponse.RaiseNotFound('Not found', '''' + BOOK_SEQ + ''' is not found');
    
        TBlobField(qryBook.FieldByName('BOOK_IMAGE')).SaveToStream(Stream);
    
        if Stream.Size = 0 then
          AResponse.RaiseNotFound('Not found', '''' + BOOK_SEQ + ''' is not found');
    
        Stream.Position := 0;
        AResponse.Body.SetStream(Stream, 'image/jpg', True);
      except
        Stream.Free;
        raise;
      end;
    end;

    위 코드는 DB에 저장된 이미지 데이터를 Stream으로 로드 해 그대로 응답합니다. 특히 Content-type을 'image/jpg'로 지정해 데이터가 이미지라는 것을 정의합니다.


    구현을 마치면, 프로젝트를 실행하고 웹브라우저에서 "http://localhost:8080/books/{item}/photo/"를 입력해 화면에 이미지가 표시되는 것을 확인합니다.



    추가 학습할 내용

    REST API 클라이언트 개발하기(REST 클라이언트 이용)

    위에서 작성한 REST API 서버와 연동하는 클라이언트를 개발합니다. REST API를 분석해 조회, 입력, 수정, 삭제, 이미지 수신 기능을 실습위주로 학습합니다.

    • http://blog.hjf.pe.kr/464

    참고/관련 자료





    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 Delphi/C++Builder

    [REST API] REST API 이해하기

    2017.05.11 17:17

    이 글에서는 REST 아키텍처를 소개합니다.


    REST는?

    REST(Representational State Transfer)는 인터넷 상의 컴퓨터 시스템간 상호 운용성을 제공하는 방법 중 하나입니다. 


    REST는 HTTP 기반으로 필요한 자원에 접근하는 방식을 정해놓은 네트워크 아키텍처입니다.

    여기서 자원이란, 저장된 데이터(DBMS 등)는 물론, 이미지/동영상/문서(PDF 등)와 같은 파일, 서비스(이메일 전송, 푸쉬 메시지 등) 등을 모두 포함합니다.


    REST는 HTTP의 주요 저자 중 한사람인 로이 필딩의 2000년 박사학위 논문에서 처음 소개되었습니다.

    REST의 제약조건

    아래 REST 제약조건을 준수하는 웹서비스를 RESTful 하다고 합니다.

    • 클라이언트/서버 : 클라이언트와 서버가 각각의 역할 구분. 서버는 API를 제공하고 API 요청 시 비지니스 로직 처리와 데이터 저장을 책임. 클라이언트는 사용자 인증, 상태(세션, 로그인 정보)관리와 서버 리소스 요청을 책임지는 구조로 역할 구분(상호 의존성을 줄임)
    • 무상태(Stateless) : REST 서버는 작업을 위한 상태정보(세션, 쿠키 등)를 관리하지 않아야 함. 시스템 영향없이 관리 및 업데이트 가능
    • 캐쉬(Cacheable) : HTTP 웹표준으로 HTTP가 가진 캐싱 기능이 적용됨
    • 계층화(Layered system) : 서버를 다중 계층으로 구성될 수 있음. 비지니스 로직을 수행하는 API 서버와 그 앞단에 사용자 인증, 암호화, 로드밸런싱 등의 계층을 추가해 구조상의 유연성 제공
    • 인터페이스 일관성(Uniform interface) : 아키텍처를 단순화하고 분리해 각 부분을 독립적으로 발전 시킬 수 있음


    REST 주요 구성요소

    REST 주요 구성요소는 리소스, 메소드, 메시지 3가지 입니다.

    • 리소스 : 접근할 대상, URI를 통해 식별
    • 메소드 : 리소스에 대한 행위, 표준 HTTP 메소드에 따라 자원에 접근(생성, 조회, 수정, 삭제)
    • 메시지 : HTTP 해더와 바디에 포함된 메시지는 메시지를 처리하기 위한 충분한 정보를 포함
    즉, REST는 어떤 자원(리소스)에 어떤 행위(메소드)를 어떻게(메시지) 할지 HTTP 기반으로 정해놓은 아키텍처입니다.

    리소스(자원)

    리소스는 URI를 통해 정의합니다.


    예를 들면, 아래와 같은 URI는 다음과 같은 의미를 갖습니다.

     URI 

     의미 

     http://api.domain.com/books/

     도서정보 콜렉션 

     http://api.domain.com/books/1/ 

     1번 도서 정보 

     http://api.domain.com/books/1/photo/

     1번 도서의 사진


    리소스명은 동사보다 명사를 활용해 어떤 자원인지 표현하는데 집중해야 합니다.(/getBooks/와 같은 리소스는 적절하지 않습니다.)


    슬래시(/)는 계층 관계를 나타내며, URI 앞쪽부터 넓은 의미로 사용합니다.

    일반적으로 계층은 컬렉션(목록) 하위에 아이템을 지정하는 방식으로 정의합니다.


    아래와 같이 URI를 구성할 수 있습니다.

    /sports/soccer/players/1/

    /(컬렉션)/(아이템)/(컬렉션)/(아이템)/


    메소드

    REST에서는 메소드를 통해 리소스에 대한 행위를 정의합니다.


    표준 HTTP 메소드 중 Get, Post, Put, Delete를 통해 자원의 CRUD를 정의합니다.

     HTTP 메소드

     자원에 대한 행위

     POST

     자원 생성(Create)

     GET

     자원 조회(Read)

     PUT

     자원 수정(Update)

     DELETE

     자원 삭제(Delete)


    Endpoint

    다음과 같이 메소드와 URI를 이용해 리소스에 접근합니다. URI 별 HTTP 메소드로 구현된 항목을 Endpoint라고 합니다.

     HTTP 메소드 

     URI(자원)

     Endpoint의 행위

     POST

     http://api.domain.com/books/

     새로운 도서정보 생성

     GET

     http://api.domain.com/books/

     도서정보 목록 조회

     GET

     http://api.domain.com/books/1/

     1번 도서정보 조회

     PUT

     http://api.domain.com/books/1/

     1번 도서정보 수정

     DELETE

     http://api.domain.com/books/1/

     1번 도서정보 삭제


    메시지

    REST에서 자원에 대한 정보는 HTTP 바디와 HTTP 해더, 응답 상태코드를 활용합니다.


    HTTP 바디

    HTTP 바디에 포함된 데이터를 통해 자원에 대한 정보를 전달합니다.

    데이터 포맷으로는 최근 JSON을 많이 사용하는 추세이며, XML과 사용자정의 포맷 등을 정해서 사용할 수도 있습니다.


    조회(GET 메소드) 요청 시 서버는 조건에 맞는 정보를 HTTP 바디에 담아 클라이언트에 응답합니다.

    생성(POST 메소드), 수정(PUT 메소드) 요청 시 클라이언트는 자원에 대한 정보를 요청 HTTP 바디에 담아 서버에 요청합니다.


    HTTP 해더

    HTTP 해더에는 HTTP 바디의 컨텐츠 종류를 명시할 수 있습니다. 해더에 정의된 컨텐츠 타입에 따라 데이터를 분석하도록 구현해야 합니다.

    요청 HTTP 해더는 "Accept" 항목으로, 응답 HTTP 해더는 "Content-type"으로 컨텐츠 타입을 설명합니다.


    몇가지 컨텐츠 타입은 다음과 같습니다.

    • application/json
    • application/xml
    • text/plain
    • image/jpeg
    • image/png
    미디어 타입, 컨텐츠 타입 자세히 보기 : https://ko.wikipedia.org/wiki/미디어타입

    응답 상태코드

    리소스 요청에 대한 응답은 응답 상태코드로 설명할 수 있습니다.
    대표적인 응답 상태코드는 아래와 같습니다.
    • 200 - 요청을 정상 수행
    • 201 - 리소스 생성 요청 성공(Post로 생성 요청 시에 한함)
    • 400 - 요청이 부적절함
    • 401 - 인증되지 않은 상태에서 보호된 리소스 요청
    • 403 - 공개되지 않은 리소스에 접근 요청(인증과 무관)
    • 404 - 존재하지 않는 리소스 요청
    • 406 - 지원하지 않는 미디어타입을 요청
    • 409 - 리소스 상태에 의해 해당 요청을 수행하지 못함
    HTTP 상태코드 자세히 보기 : https://ko.wikipedia.org/wiki/HTTP_상태_코드

    REST API 구현

    REST 기반으로 서비스 API를 구현한 것을 REST API라고 합니다.

    REST API 구현의 특징

    최근 OpenAPI(누구나 사용할 수 있도록 공개된 API: 구글 맵, 공공 데이터 등), 마이크로 서비스(하나의 큰 애플리케이션을 여러 개의 작은 애플리케이션으로 쪼개어 변경과 조합이 가능하도록 만든 아키텍처) 등을 제공하는 업체 대부분은 REST API를 제공합니다. 


    또, 사내 시스템들도 REST 기반으로 시스템을 분산해 확장성과 재사용성을 높여 유지보수 및 운용을 편리하게 할 수 있습니다. 


    REST는 HTTP 표준을 기반으로 구현하므로, HTTP를 지원하는 프로그램 언어로 클라이언트, 서버를 구현할 수 있습니다. 

    즉, REST API를 제작하면 델파이 클라이언트 뿐 아니라, 자바, C#, 웹 등을 이용해 클라이언트를 제작할 수 있습니다. 물론 반대의 방법도 가능합니다.


    델파이로 REST API 구현

    델파이의 HTTP 라이브러리를 이용핸 REST API를 구현할 수 있습니다.

    REST API 구현해 특화된 기술은 서버 측 기술로는 EMS 서버 클라이언트 기술로는 REST 클라이언트 라이브러리가 있습니다.

    서버(Back-End) 프레임워크

    • RAD Server(EMS Server) - REST API Endpoint 제공
    • WebBroker - RAD 스튜디오(델파이, C++빌더) 웹 개발 프레임워크
    • DataSnap - RAD 스튜디오 멀티티어 개발 프레임워크, TCP/IP, HTTP 프로토콜 제공
    • Delphi MVC Framework - 오픈소스 웹서비스 개발 프레임워크
    • mORMot - 오픈소스 SOA, ORM 개발 프레임워크

    클라이언트(Front-End) 프레임워크

    • REST Client - REST 클라이언트 프레임워크
    • Net HTTP Client - 네이티브 HTTP 클라이언트 프레임워크
    • Indy Library - 범용 네트워크 라이브러리(HTTP 클라리언트, 서버 제공)


    추가 학습할 내용

    EMS 패키지 프로젝트 시작하기

    EMS 패키지는 REST API 리소스와 엔드포인트 개발을 지원합니다. EMS 패키지 프로젝트를 만들고, 배포하는 내용을 학습할 수 있습니다.
    • http://blog.hjf.pe.kr/459

    REST API 서버 개발하기(엔드포인트 구현, RAD 서버 이용)

    EMS 패키지를 이용해 REST API를 제공하는 서버를 개발합니다. 미리 준비된 DB를 이용해 조회, 입력, 수정, 삭제, 이미지 제공 등의 기능을 실습위주로 학습합니다.

    • http://blog.hjf.pe.kr/463

    REST API 클라이언트 개발하기(REST 클라이언트 이용)

    위에서 작성한 REST API 서버와 연동하는 클라이언트를 개발합니다. REST API를 분석해 조회, 입력, 수정, 삭제, 이미지 수신 기능을 실습위주로 학습합니다.

    • http://blog.hjf.pe.kr/464

    참고 링크



    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 Delphi/C++Builder