행복한 아빠

[Grails1.0 사용자 가이드] 13. 웹서비스 본문

Grails

[Grails1.0 사용자 가이드] 13. 웹서비스

행복한아빠 2008. 3. 12. 13:38


13. 웹서비스

웹 서비스는 웹 애플리케이션에 웹 API를 제공하는 것을 이야기한다. 그리고 웹 서비스는 전형적으로 SOAP이나 REST로 구현한다.

13.1 REST
REST는 실제로는 그 자체로 기술은 아니고 아키텍쳐 패턴에 가깝다. RETS는 대단히 단순하며 통신 매개로 평이한 XML이나 JSON을 사용한다. 또한 기반 시스템의 표현과 GET, PUT, POST, DELETE와 같은 HTTP 메소드를 사용하는 URL 패턴과 결합한다.

HTTP 메소드는 액션으로 매핑된다. 예를 들면 데이터 조회에는 GET, 데이터 생성에는 PUT, 데이터 업데이트 등에는 POST를 사용한다. 이런 면에서 REST는 CRUD에 잘 들어맞는다.

URL 패턴
Grails로 REST를 구현하기 위한 첫번째 단계는 RESTfull URL 매핑을 제공하는 것이다.

static mappings = {
    "/product/$id?"(controller:"product"){
        action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"]
    }
}

여기서 우리는 컨트롤러에서 RESTful API를 제공하기 위해 HTTP 메소드로 매핑하는 URL 매핑 기능을 사용했다. GET, PUT, POST 그리고 DELETE와 같은 각 HTTP 메소드는 컨트롤러의 고유 액션으로 매핑된다.

XML 마셀링(marshaling) - 조회
컨트롤러 구현체는 GET 메소드를 구현하기 위해 Grails의 XML 마셀링을 사용할 수 있다.

import grails.converters.*
class ProductController {
    def show = {
        if(params.id && Product.exists(params.id)) {
            def p = Product.findByName(params.id)
            render p as XML
        }
        else {
            def all = Product.list()
            render all as XML
        }
    }
    ..
}

여기서 하는 일은 만일 id가 있으면 이름으로 Product을 찾아 반환하고 아니면 모든 Proudct을 반환한다. 이 방법으로 /produts로 간다면 모든 product들을 얻을 수 있으며 아니면 /product/MacBook으로 가면 단지 MacBook만 얻을 수 있다.

XML 마셀링 - 업데이트
PUT이나 POST로 업데이트 하기 위해서 들어오는 XML 패킷을 읽는 능력을 가진 params 객체를 사용할 수 있다. 유입되는 XML 패킷을 보자.

<?xml version="1.0" encoding="ISO-8859-1"?>
<product>
    <name>MacBook</name>
    <vendor id="12">
        <name>Apple</name>
    </vender>
</product>

params 객체를 통해 데이터 바인딩에서 설명한 동일한 기술을 사용하여 이 XML 패킷을 읽을 수 있다.

def save = {
    def p = new Product(params['product'])
    if(p.save()) {
        render p as XML
    }
    else {
        def errors = p.errors.allErrors.collect { g.message(error:it) }
        render(contentType:"text/xml") {
            error {
                for(err in errors) {
                    message(error:err)
                }
            }
        }
    }
}

이 예제에서 'product'키를 이용하여 params 객체의 인덱스를 찾아 Product 클래스의 생성자를 이용항 자동으로 XML을 바인드하였다. 다음 라인이 흥미롭다.

def p = new Product(params['product'])

이 라인은 폼 데이터 submit에서 XML 요청을 다루기 위해 코드 변경이 필요없다. 정확히 동일한 기술을 JSON 요청에서도 사용한다.

사용자 삽입 이미지
만일 서로 다른 클라이언트에 대해 서로 다른 응답(REST, HTML 등)이 필요하면 content negotation을 사용할 수 있다.

그런 후 Product 객체는 저장되고 XML로 렌더링된다. 그렇지 않으면 Grails 유효성 검사 기능을 이용하여 에러 메시지를 생성한다.

<error>
    <message>The property 'title' of class 'Person' must be specified</message>
</error>


13.2 SOAP
Grails는 SOAP 통합을 위해 인기있는 XFire SOAP 스택을 이용한 XFire 플러그인을 통해 SOAP을 지원한다. XFire 플러그인은 특별한 expose 속성을 이용하여 Grails 서비스를 SOAP 서비스로 노출한다.

class BookService {
    static expose=['xfire']
    Book[] getBooks(){
        Book.list() as Book[]
    }
}

WSDL은 다음과 같은 위치에서 접근할 수 있다.
http://127.0.0.1:8080/your_grails_app/services/book?wsdl

XFire 플러그인에 대한 더 자세한 정보는 wiki의 문서를 참조한다.


13.3. RSS와 Atom
Grails는 직접 FSS나 Atom을 지원하지는 않는다. render 메소드의 XML 기능으로 RSS나 ATOM 피드를 구축할 수 있다. 여하튼 인기있는 ROME 라이브러리를 이용한 RSS와 Atom 빌더를 Grails에서 지원하기 위해 Feeds 플러그인이 있다. 이것의 사용 예제는 아래에서 볼 수 있다.

def feed = {
    render(feedType:"rss", feedVersion:"2.0") {
        title = "My test feed"
        link = "http://your.test.server/yourController/feed"
        Article.list().each() {
            entry(it.title) {
                link = "http://your.test.server/article/${it.id}"
                it.content // return the content
            }
        }
    }
}

---
원문: 13. Web Services
0 Comments
댓글쓰기 폼