행복한 아빠

[Grails1.0 사용자 가이드] 7. 유효성검사 본문

Grails

[Grails1.0 사용자 가이드] 7. 유효성검사

행복한아빠 2008. 3. 11. 20:41


7. 유효성 검사

Grails 유효성 검사 능력은 Spring의 Validator API와 데이터 바인딩에 기반을 둔다. 여하튼 Grails는 여기에 더하여 제약조건 메커니즘을 이용하여 일관성 있는 유효성 검사를 위한 "제약조건" 정의 방법을 제공한다.

Grails의 제약조건은 유효성 검사 규칙을 선언적으로 지정하는 방법이다. 대부분 일반적으로 도메인 클래스에 적용하나 URL Mapping 그리고 명령객체(Command Object)에서도 제약조건을 지원한다.

7.1 제약조건 선언
도메인 클래스에서는 코드블럭이 할당된 constraints 속성에 제약조건을 정의한다.

class User {
    String login
    String password
    String email
    Integer age
    static constraints = {
        …
    }
}

그런 다음 속성 이름에 대응하는 메소드를 호출하는데 여기에 named 파라메터로 제약조건을 지정한다.

class User {
    ...
    static constraints = {
        login(size:5..15, blank:false, unique:true)
        password(size:5..15, blank:false)
        email(email:true, blank:false)
        age(min:18, nullable:false)
    }
}

이 예제에서 우리는 login 속성은 문자 길이가 5와 15사이이어야 하고 빈칸이 없어야 하고 유일해야 한다고 선언했다. 또한 password, email 그리고 age 속성에 제약조건을 적용했다.

사용자 삽입 이미지
사용 가능한 제약조건의 완전한 참조는 레퍼런스 가이드에서 찾을 수 있다.


7.2 제약조건 검사

유효성검사 기본
도메인 클래스의 유효성검사를 위해서 모든 인스턴스가 가지고 있는 validate 메소드를 호출할 수 있다.

def user = new User(params)
if (user.validate()) {
    // user로 뭔가를 한다.
}
eles {
    user.errors.allErrors.each {
        println it
    }
}

도메인 클래스의 errors 속성은 Spring Errors 인터페이스의 인스턴스이다. Errors 인터페이스는 유효성검사 에러를 살펴볼(navigate) 수 있는 메소드와 원래 값을 조회할 수 있는 메소드를 제공한다.

검사 단계
Grails에는 근본적으로 2단계의 검사단계가 있다. 첫번째 단계는 데이터 바인딩으로 요청 파라메터를 다음과 같은 인스턴스에 바인드할 때 발생한다.

def user = new User(params)

이 지점에서 String을 Date로 변환하는 것 같은 타입변환에 의해 이미 errors 속성을 가질 수도 있다. 이것들을 검사하고 Errors API를 이용하여 원래의 입력값을 볼 수도 있다.

if(user.hasErrors()) {
    if(user.hasFieldError("login")) {
        println user.getFieldError("login").rejectedValue
    }
}

유효성 검사의 두번째 단계는 validatesave를 호출할 때 발생한다. 이것은 개발자가 정의한 constraints를 통해 Grails가 한계값을 검사할 때이다. 예를 들어 저장하는 save 메소드를 실행하기전 기본으로 validate를 호출한다. 따라서 다음과 같이 코드를 작성할 수 있다.

if (user.save()) {
    return user
}
else {
    user.errors.allErrors.each {
        println it
    }
}


7.3 클라이어트에서의 유효성검사

에러 보여주기
전형적으로 유효성검사 에러가 발생하면 렌더링을 하기 위해 뷰(페이지)가 뒤로 돌아가길 원할 것이다. 또한 에러를 표현하는 방법이 필요할 것이다. Grails는 에러를 다루는 풍부한 태그들을 지원하고 있다. 단순히 목록으로 에러를 표현하고 싶다면 renderErrors를 사용할 수 있다.

<g:renderErrors bean="${user}" />

좀 더 제어가 필요하다면 hasErroreachError를 사용할 수 있다.

<g:hasError bean="${user}">
    <ul>
        <g:eachError var="err" bean="${user}">
            <li>${err}</li>
        </g:eachError>
    </ul?
</g:hasError>


에러 강조하기(highlighting)
필드에 틀린 입력값이 있을 경우 빨간 박스나 어떤 표시를 사용하여 강조하는 것은 종종 유용하다. hasErrors를 메소드로 호출하여 이것을 할 수 있다. 예를 들어

<div class="value ${hasErrors(bean:user,field:'login','errors')}">
    <input type="text" name="login" value="${fieldValue(bean:user,field:'login')}" />
</div>

이 코드가 하는 일은 user의 login 필드가 에러가 없는지 검사하여 에러가 있으면 div를 강조하기 위한 errors CSS 클래스를 div에 추가한다.

입력값 복구
각 에러는 실제로 Spring에 있는 FieldError 클래스의 인스턴스인데 이것은 본래 입력값을 유지하고 있다. 이것은 fieldValue 태그를 이용하여 사용자에게 입력받은 값을 복구하기 위해 에러 객체를 사용할 수 있다는 점에서 유용하다.

<input type="text" name="login" value="${fieldValue(bean:user, field:'login')}" />

이 코드는 User bean에 FieldError가 있고 login필드의 본래 입력값을 획득할 수 있는지 살펴볼 것이다.

7.4 유효성검사와 국제화
Grails의 에러에 대해 주목할 또 다른 중요한 점은 에러를 보여주는 메시지가 어디에도 하드 코드되지 않는다는 것이다. Spring의 FieldError 클래스는 근본적으로 Grails의 i18n을 이용하여 메시지 번들로 메시지를 결정한다.

제약조건과 메시지 코드
규칙(convention)에 의해 메시지 코드를 결정한다. 예를 들어 앞에서 본 제약조건을 살펴보자

class User {
    ...
    static constraints = {
        login(size:5..15, blank:false, unique:true)
        password(size:5..15, blank:false)
        email(email:true, blank:false)
        age(min:18, nullable:false)
    }
}

만일 blank 제약조건을 위반했다면 Grails는 약속에 의해 다음 형식으로 메시지 코드를 찾는다.

[클래스이름].[속성이름].[제약코드]

이 blank 제약조건의 경우는 user.login.blank가 될 것이다. 따라서 grails-app/i18n/messages.properties 파일안에 다음과 같은 메시지가 필요할 것이다.

user.login.blank=Your login name must be specified!

각 제약조건이 어떤 코드인지를 보기 위해서는 레퍼런스 가이드에서 각 제약조건을 참조한다.

메시지 보여주기
renderErrors 태그는 message 태그를 사용하여 자동으로 메시지를 찾아준다. 어쨌거나 메시지 표현을 더 제어하기를 원한다면 개발자 스스로 할 필요도 있다.

<g:hasErrors bean="${user}">
    <ul>
        <g:eachError var="err" bean="${user}">
            <li><g:message error="${err}" /></li>
        </g:eachError>
    </ul>
</g:hasErrors>

이 예제에서 주어진 에러의 메시지를 읽기 위해 eachError 태그의 몸체안에 message 태그와 error 아규먼트를 사용했다.

---
본문: 7. Validation

0 Comments
댓글쓰기 폼