행복한 아빠

[Grails1.0 사용자 가이드] 6. 웹 계층 - 4 본문

Grails

[Grails1.0 사용자 가이드] 6. 웹 계층 - 4

행복한아빠 2008. 3. 7. 19:32


6. 웹 계층 - 4

6.4 URL 매핑
여태까지 문서에서 URL을 위한 규칙(convention)은 기본인 /controller/action/id 이었다. 하지만 이러한 규칙(convention)이 Grails에 내장된(hard wired) 것은 아니다. 사실은 grails-app/conf/UrlMappings.groovy에 위치한 URL Mapping 클래스에서 제어한다.

UrlMappings 클래스는 코드 블럭을 가지는 mappings라는 하나의 속성을 가지고 있다.

class UrlMappings {
    static mappings = {
    }
}


6.4.1 컨트롤러와 액션에 매핑하기
간단한 매핑을 만들기 위해서는 그냥 관련 URL을 메소드 이름으로 하고 매핑하기 위한 컨트롤러액션을   named 파라메터로 지정한다.

"/product"(controller:"product", action:"list")

이 예제에서 우리는 /product URL을 ProductController의 list 액션으로 매핑했다. 물론 컨트롤러의 기본 액션으로 매핑하기 위해 액션 정의를 생략할 수 있다.

"/product"(controller:"product")

다른 방법의 문법은 메소드에 전달하는 블럭 안에 컨트롤러와 액션을 지정하는 것이다.

"/product" {
    controller = "product"
    action = "list"
}


어떤 문법을 사용할 지는 개인 선호도에 달려있다.

6.4.2 내장(Embedded) 변수

간단한 변수들
이전 장에서는 평범한 URL을 고정된 "토큰"들로 어떻게 매핑하는지 보여줬다. URL 매핑에서 말하는 토큰은 각 슬래쉬 / 문자 사이의 문자들의 sequence이다. 고정된 토큰은 /product과 같이 잘 정의된 것을 말한다. 그러나 많은 경우 실행시간 전까지도 특정 토큰의 값이 어떤 것인지 알지 못한다. 이런 경우 URL에 변수 위치지정자(placeholder)를 사용할 수 있다. 예를 들면

static mappings = {
    "/product/$id"(controller:"product")
}

이 경우 $id 변수를 두번째 토큰으로 포함함으로써 Grails는 자동으로 두번째 토큰을 id라는 파라메터로 매핑한다(params 객체에서 사용이 가능함). 예를 들어 주어진 URL /product/MacBook에 대해 다음 코드는 "MacBook"을 response에 렌더링한다.

class ProductController {
    def index = { render params.id }
}

물론 좀 더 복잡한 매핑 예제를 구성할 수 있다. 예를 들어 전통적인 블로그 URL 포맷은 다음과 같이 매핑한다.

static mappings = {
    "/$blog/$year/$month/$day/$id"(controller:"blog", action:"show")
}

위 매핑으로 다음과 같은 URL을 매핑할 수 있다.

/graemerocher/2007/01/10/my_funky_blog_entry

URL의 각 토큰은 params 객체에서 사용할 수 있는 year, month, data, id 등으로 매핑된다.

컨트롤러와 액션 이름 동적으로 결정
동적으로 컨트롤러와 액션 이름을 구성하기 위해 변수를 사용할 수 있다. 사실 기본 Grails URL 매핑은 이 기술을 사용한다.

static mappings \ {
    "/$controller/$action?/$id?"()
}

여기에서 컨트롤러, 액션 이름 그리고 id는 URL 안에 포함된 controller, action 그리고 id 변수로 부터 획득한다.

선택적인 변수
기본 매핑의 또 다른 특징은 변수 끝에 ?을 붙임으로 이것을 선택적인 토큰으로 만들 수 있는 능력이다. 다음 예제에서 블로그 URL 매핑에 이 기술을 적용하여 보다 유연한 링크를 가질 수 있다.

static mappings = {
    "/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show")
}

이 매핑으로 아래의 모든 URL들은 적절한 파라메터 매치를 하여 params 객체에 넣어진다(populate).

/graemerocher/2007/01/10/my_funky_blog_entry
/graemerocher/2007/01/10
/graemerocher/2007/01
/graemerocher/2007
/graemerocher


임의의 변수
단순히 매핑에 전달하는 블럭에 임의의 변수를 설정함으로써 URL 매핑에서 컨트롤러로 임의의 파라메터를 전달할 수 있다.

"/holiday/win" {
    id = "Marrakech"
    year = 2007
}

이 변수는 컨트롤러에 전달되는 params 객체에서 사용 가능하다.


동적으로 결정되는 변수들
하드 코드된 임의의 변수들이 유용하긴 하지만 어떤 경우는 실행시간 요소(factor)를 기반으로 변수의 이름이 계산될 필요가 있다. 이것 또한 가능한데 변수 이름에 블럭을 지정하면 된다.

"/holiday/win" {
    id = { params.id }
    isEligible = { session.user != null }  // 로그인해야 함
}

위 경우 블럭의 코드는 URL이 실제로 매치될 때 결정된다. 따라서 모든 종류의 로직과 결합에 사용할 수 있다.

6.4.3 뷰에 매핑하기
컨트롤러나 액션 없이
URL의 뷰를 결정하고 싶을 경우 이것도 역시 가능한다. 예를 들어 루트 URL /를 grails-app/views/index.gsp에 있는 GSP로 매핑하고 싶을 경우 다음과 같이 한다.

static mappings = {
    "/"(view:"/index")    // 루트 URL 매핑
}

또 다르게 특정 컨트롤러를 특정 뷰로 지정할 필요가 있을 경우 다음과 같이 한다.

static mappings = {
    "/help"(controller:"site",view:"help")    // to a view for a controller
}


6.4.4 응답 코드 매핑
또한 Grails는 HTTP 응답 코드를 컨트롤러, 액션 또는 뷰로 매핑할 수 있다. 당신이 할 일은 관심있는 응답코드를 메소드 이름으로 사용하는 게 전부이다.

static mappings = {
    "500"(controller:"errors", action:"serverError")
    "404"(controller:"errors", action:"notFound")
    "403"(controller:"errors", action:"forbidden")
}

또는 다르게 그냥 사용자 정의 에러 페이지를 원할 경우도 있다.

static mappings = {
    "500"(view:"/errors/serverError")
    "404"(view:"/errors/notFound")
    "403"(view:"/errors/forbidden")
}


6.4.5 HTTP 메소드로 매핑
HTTP 메소드(GET, POST, PUT 또는 DELETE)
를 기반으로 매핑을 구성할 수도 있다. 이것은 특히 RESTful API이나 HTTP 메소드를 기준으로 매핑을 제한하는데 유용하다.

아래 예제는 BookController의 RESTful API URL 매핑을 제공한다.

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


6.4.6 와일드카드 매핑
Grails의 URL 매핑 메커니즘은 와일드카드 매핑 역시 지원한다. 예를 들어 다음 매핑을 살펴보자.

static mappings = {
    "/images/*.jpg"(controllers:"image")
}

이 매핑은 /image/logo.jsp 같은 모든 패스를 images로 맞춰 준다. 물론 변수를 사용하여 동일한 효과를 낼 수 있다.

static mappings = {
    "/images/$name.jpg"(controllers:"image")
}

어찌되었든, 한 레벨 이상 더 매치하기 위해 더블 와일드카드를 쓸수도 있다.

static mappings = {
    "/images/**.jpg"(controllers:"image")
}

이 경우 이 매핑은 /image/logo.jpg은 물론 /image/other/log.jpg도 매칭한다. 더욱이 더블 와일드카드 변수를 사용할 수 있다.

static mappings = {
 // will match /image/logo.jpg and /image/other/logo.jpg
 "/images/$name**.jpg"(controllers:"image")
}

이 경우 이것은 name 파라메터의 와일드카드와 매칭되는 패스를 저장하며 이는 params 객체에서 획득할 수 있다.

def name = params.name
println name // "logo.jpg"나 "other/logo.jsp"를 출력


6.4.7 link 자동으로 다시 쓰기(Re-Writing)
또 다른 URL 매핑의 대단한 기능은 URL 매핑은 자동으로 link 태그의 행동을 조정(customize)해 주어서 매핑을 바꾸더라도 link를 변경할 필요가 없다.

이것은 URL 매핑에서 link를 역공학(reverse engineer)하는 URL 다시 쓰기 기술을 통해 이루어진다. 따라서 앞의 장의 블로그 같은 매핑이 있다고 하자.

static mappings = {
    "/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show")
}

다음과 같이 link 태그를 사용한다면

<g:link controller="blog" action="show" params="[blog:'fred', year:2007]">My Blog</g:link>
<g:link controller="blog" action="show" params="[blog:'fred', year:2007, month:10]">My Blog - October 2007 Posts</g:link>

Grails는 자동으로 올바른 포맷으로 URL을 다시 쓴다.

<a href="/fred/2007">My Blog</a>
<a href="/fred/2007/10">My Blog - October 2007 Posts</a>


6.4.8 제약조건 적용
URL 매핑도 역시 Grails의 일관된 제약조건 검증 메커니즘을 지원한다. 이는 URL을 어떻게 매치할지에 대해 더욱 제한된 방법을 제공핞다. 예를 들어 이전의 블로그 예제를 다시 보면 현재는 매핑이 아래와 같다.

static mappings = {
    "/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show")
}

이것은 다음과 같은 URL을 허용한다.

/graemerocher/2007/01/10/my_funky_blog_entry

어쨌거나 다음 URL도 허용한다.

/graemerocher/not_a_year/not_a_month/not_a_day/my_funky_blog_entry

이것은 컨트롤러 코드에서 좀 영리한 파싱을 하도록 강요하는 문제가 있다. 다행이도 URL 토큰들을 좀 더 검사하여 URL 매핑에 제약을 줄 수 있다.

"/$blog/$year?/$month?/$day?/$id?" {
     controller = "blog"
     action = "show"
     constraints {
          year(matches:/d{4}/)
          month(matches:/d{2}/)
          day(matches:/d{2}/)
     }
}

이 경우 이 제약조건은 year, month 그리고 day 파라메터가 특정 유효한 패턴으로 매치된다는 것을 보장하여 검사를 하지 않았을 때 올 수 있는 부담(파싱 등)으로부터 구원해 준다. (오 감사~)

---
원문:  6.4 URL Mappings

0 Comments
댓글쓰기 폼