메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

한빛랩스 - 지식에 가능성을 머지하다 / 강의 콘텐츠 무료로 수강하시고 피드백을 남겨주세요. ▶︎

IT/모바일

펄을 이용한 RESTful 웹 서비스 개발(2)

한빛미디어

|

2008-04-04

|

by HANBIT

12,119

제공 : 한빛 네트워크
저자 : Andrew Sterling Hanenkamp
역자 : 이대엽
원문 : Developing RESTful Web Services in Perl

GET으로 조회하기

여러분은 서버에서 ID가 숫자와 대시(-)로 이루어져 있는 "/=/model/book/id/"와 같은 URL을 방문하여 주어진 ID에 해당하는 서적을 설명하는 YAML 파일을 가져올 수 있을 것이다. 해당 ID에 대한 책이 아무것도 발견되지 않을 수도 있는데, 그런 경우 여러분은 "404 Not Found" 오류를 전달받게 될 것이다.

다음은 예제 서버에서 중요한 코드를 가져온 것이다. 이 코드 조각에서 $id 변수는 이미 URL을 나타내는 ID 값으로 설정되어 있다.
# 자원 파일을 찾는다
my $filename = get_local_path($id);
if (-f $filename) {

    # 파일을 열고 내용을 읽어 자원을 출력한다
    open my $bookfh, $filename
    or barf 500, "I Am Broke", "Cannot open $filename: $!";

    print $q->header("text/yaml");
    print do { local $/; <$bookfh> };
}

# 아무런 자원이 존재하지 않음
else {
    barf 404, "Where is What?", "Book for $id does not exist.";
}
먼저 로컬 디스크에서 주어진 파일명을 찾는다. 코드에서는 파일이 존재하는지 확인하고 그렇지 않으면 404를 반환한다. 그렇지 않으면 파일의 내용을 읽어 들여 YAML 데이터를 포함하는 "text/yaml" 응답으로 전송한다. 여기에서는 통신하는데 사용하고 있는 형식으로 디스크상에 데이터를 저장하고 있으므로 파일을 그대로 보낼 수가 있다. 이것이 데이터베이스 레코드나 기타 다른 것이었다면 YAML::Dump()를 이용하여 데이터를 YAML 형식으로 직렬화해야 할 수도 있었을 것이다.

만약 여러분이 위의 CGI 스크립트를 설치했다면 여러분은 레코드를 추가한 다음 바로 레코드 하나를 가져올 수가 있다. 가령 여러분은 브라우저에서 다음 주소를 방문할 수도 있을 것이다: http://localhost/cgi-bin/library.cgi/=/model/book/id/0-936083-11-5 여러분은 다운로드된 파일을 저장하거나 열지 선택해야 할 것이다.

POST로 생성하기

이제 레코드를 가져오는 법(아직 레코드를 만드는 법은 배우지 않았지만)을 배웠으므로 어떻게 새로운 책을 시스템에 집어넣는지 배워 보도록 하자. 이는 POST를 이용하여 구현되어 있다. 이 구현에서 서버는 항상 새로 생성된 책 레코드에 ID를 할당할 것이나 그 ID는 파일에 기록된 ISBN를 토대로 만들어 질 것이다("isbn" 필드가 있다면). 여러분이 이미 전송된 ISBN을 가진 책 자원을 생성하려 할 경우에는 오류가 발생할 것이다.

다음은 여러분이 "/=/model/book"에 요청을 POST할 때 실행될 코드이다. 설명을 좀 더 쉽게 하기 위해 코드를 약간 나누었다.
# 입력된 서적이 정상적인지를 확인한다
my $book = check_book( $q->param("POSTDATA") );

# 만약 책에 ISBN이 있고(어떤 책은 ISBN이 없기도 하다!), 해당 ISBN이 이미 
# 시스템에 들어 있다면 여기에서는 POST를 통해 갱신이 이루어지는 것을 
# 허용하지 않으므로 실행을 중단한다(die).
if ($book->{isbn} and -f get_local_path($book->{isbn})) {
    barf 500, "Not Gonna Do It",
        "A POST may not be used to update an existing book.";
}

# 데이터가 정상적이다!
첫 번째로 해야 할 일은 데이터의 정상성(sanity) 여부를 검사하는 것이다. check_book() 함수는 몇 가지 작업을 수행하여 요청의 정상성을 검사한다. 여러분이 직접 코드를 살펴 세부적인 사항을 확인해 볼 수도 있겠지만, 이 함수는 발생한 문제의 종류에 따라 "415 Unsupported Media Type"이나 "400 Bad Request", "500 Internal Server Error" 오류를 초래할 것이라 간단히 말할 수가 있겠다. 나는 가능한 경우 가장 적절한 상태 코드(status code)를 선정하고자 했다. 여러분이 주어진 응답에 대해 가장 최선의 코드를 보낸다고 보장하려면 HTTP/1.1 프로토콜의 Status Code Definitions에 익숙해 질 것을 적극 권장한다. 그리고 어떠한 상태 코드를 반환해야 할지 분명하지 않다면 반환할 수 있는 가장 일반적인 오류인 "500 Internal Server Error"를 클라이언트에게 반환하도록 한다.
# ID를 계산하는데, 이것은 ISBN이나 생성된 ID이다
my $id = $book->{isbn} ? $book->{isbn} : next_id;

# 레코드에 참조 ID를 저장한다
$book->{id} = $id;

# 자원을 저장한다
eval { YAML::DumpFile(get_local_path($id), $book) };
barf 500, "I Am Broke", $@ if $@;
이제 여러분은 데이터가 정상적인지를 알았으므로 책의 ID를 설정하고 YAML 파일로 책을 저장할 것이다. 만약 책에 ISBN이 있다면 그 ISBN가 ID로 사용된다. 책에 나열된 ISBN 이 책에 없다면 next_id() 함수로 새로운 ID가 생성된다. 그런 다음 서버에서는 YAML::DumpFile()을 이용하여 책을 디스크의 적절한 로컬 경로에 YAML 형식으로 저장한다.
# 최종 사용자에게 성공했음을 알린다
my $resource_url = absolute_url("/=/model/book/id/".$id);
print $q->header(
    -status   => 201,
    -type     => "text/html",
    -location => $resource_url,
);
print $q->h1("Created $book->Developing RESTful Web Services in Perl");
print $q->ul(
    $q->li(
        $q->a({ href => $resource_url }, $resource_url)
    )
);
마지막으로 우리는 클라이언트에게 "201 Created" 응답을 반환하여 완료할 것이다. 여러분은 자원을 생성할 때 클라이언트에게 201이나 202 응답을 반환하도록 해야 한다. 일반적으로 이것이 생성에 있어서는 200이나 204보다 더 낫기 때문이다. 201을 이용하면 여러분은 응답에 "Location" 헤더(이 예제에서 했던 것처럼)를 지정할 수도 있을 것이다. "Location" 헤더는 새 항목의 URL을 가리켜야만 한다. 만약 여러분이 해당 항목을 곧바로 생성할 수가 없으면 "202 Accepted" 상태를 고려해 볼 수도 있을 것이다. 보다 상세한 내용에 대해서는 HTTP/1.1 명세를 확인한다.

그런데 아파치에서는 200 상태로 응답하고 "Location" 헤더는 포함하지 않도록 한다. 아파치는 200을 302으로 변환하는데, 이는 일반적으로 게으른 웹 프로그래머에게는 도움이 될지도 모르겠지만 RESTful 인터페이스에서는 바람직한 바가 아니다. "Location" 헤더가 200에는 적절하지 않으므로 생성을 위해 "Location" 헤더를 포함하는 경우에는 확실히 201을 반환하도록 한다.

PUT으로 갱신하기

RESTful 인터페이스에서 PUT은 정확히 GET의 반대이다. GET은 서버에서 콘텐츠를 가져온다. PUT은 서버로 콘텐츠를 보낸다. 아래의 예제 서버 코드에서 $id라는 이름의 변수는 이미 "/=/model/book/id/"과 같은 URL의 마지막 부분으로 설정되어 있다. 아래는 예제 서버가 어떻게 PUT 처리를 시작하는지 보여 준다.
# 입력된 책의 정상성 여부를 점검
my $book = check_book( $q->param("PUTDATA") );

# 책이 이미 존재하는지를 확인하고 존재하지 않는다면 오류를 반환한다
my $resource_path = get_local_path($id);
unless (-f $resource_path) {
    barf 500, "Not Gonna Do It",
        "Cannot use PUTs for creating a new resource.";
}
위 코드는 POST와 비슷해 보인다. 나는 데이터가 정상적인지를 확인하는 정상성 점검으로 시작했다. check_book()을 또 한번 사용하는 것에 더불어 여기에서는 추가적으로 테스트를 수행하여 이것이 갱신인지를 확인한다. 이 REST 서버에서는 PUT으로는 레코드를 생성할 수 없게 하였다. 여러분의 REST API는 PUT을 이용하여 생성하는 것을 허용할 수도 있겠지만 이는 클라이언트에서 PUT을 할 수 있고, PUT에 대한 적절한 URL이 지정되어 있을 경우에만 허용되어야 한다.
# ID를 지정
$book->{id} = $id;

# 자원을 저장
eval { YAML::DumpFile($resource_path, $book) };
barf 500, "I Am Broke", $@ if $@;
이는 POST와 비슷하게 보이지만 URL에서 ID를 가져온다는 점에서 약간 차이가 있다(게다가 바뀌지도 않을 것이다). 바로 이 부분이 이 인터페이스가 다소 오동작 할 수도 있는 곳이다. 여러분은 실제로 여기에서 ISBN을 변경하여 ID와 달라지게 할 수도 있는데, 그렇게 하는 것은 바람직하지 않다. 글쎄, 모르겠다. 나는 정말 게을러서 부지런한 독자가 이 부분을 고치도록 남겨 두겠다.
# 최종 사용자에게 성공했음을 알린다
print $q->header("text/html");
print $q->h1("Updated $book->Developing RESTful Web Services in Perl");
마지막으로 클라이언트에게 작업이 성공했음을 알려 주는 응답을 반환한다.

DELETE로 삭제하기

예제 서버에서 마지막으로 알아볼 동사는 DELETE이다. 우리는 이미 GET과 PUT에서 사용했던 URL과 같은 "/=/model/book/id/"을 사용할 것이다. 아래 코드 조각에서 $id는 이미 로 초기화되어 있다.
# 책이 실제로 존재하는지 확인
my $resource_path = get_local_path($id);
unless (-f $resource_path) {
    barf 404, "Where is What?",
        "Nothing here to delete.";
}

# 완전 삭제!
unlink $resource_path;

# 삭제 결과를 알려줌
print $q->header("text/html");
print $q->h1("Deleted $id");
이 예제는 꽤 간단하지만 살펴볼 필요가 있다. 먼저 해당 ID를 로컬 디스크상의 어디에 있는지 찾는다. 그런 다음 먼저 삭제할 파일이 있는지를 확인한다. 파일이 없으면 404 오류를 반환한다. 파일이 존재하면 그 파일을 삭제한다. 마지막으로 200 응답과 파일이 삭제되었다는 사실을 알려 주는 내용을 반환한다.

예제 REST 서버의 특징에 관해 논의하는 것으로 이야기를 마무리하겠다. 그런 다음에는 몇 가지 중요한 확장 가능성에 관해 논의할 수가 있을 것이다.

RESTful 클라이언트를 주시하라

지금까지 우리는 예제 REST 서버에서 가장 핵심적인 구성 요소에 관해 설명했다. 이 기사가 여러분만의 RESTful 웹 서비스를 개발할 때 가장 중요한 개념을 설명하기 위한 원칙과 펄에서 사용할 수 있는 실용적인 도구를 알게 된 계기가 되었길 바란다.

다음 기사에서는 직접 libwww-perl로 작성한 클라이언트 도구를 이용하여 이러한 모든 기능에 접근하는 법을 보여 줄 것이다. 뿐만 아니라 클라이언트와 서버에 제작될 수 있는 확장 기능을 고민해 보고 서비스의 능력을 향상시키고 REST 웹 서비스를 이용하여 독자적으로 만드는데 도움되었던 링크를 알려주도록 하겠다.

그럼 그때까지 화이팅!

참고자료 저자 앤드류 스털링 하넨캄프는 자랑스런 캔자스주 사람이며 대부분의 시간을 부인과 아들, 그리고 펄 프로그래밍과 자신의 웹 사이트, 정원일 피해 다니기로 보낸다.
TAG :
댓글 입력
자료실

최근 본 상품0