맨위로가기

Grails

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

Grails는 Java 플랫폼을 기반으로 하는 오픈 소스 웹 애플리케이션 프레임워크이다. XML 설정을 불필요하게 하고, 즉시 사용 가능한 개발 환경과 믹스인을 통한 기능 제공을 특징으로 한다. 모델-뷰-컨트롤러(MVC) 아키텍처를 따르며, GORM을 사용하여 데이터베이스에 영속성을 제공한다. 또한, 스캐폴딩을 지원하여 CRUD 작업을 쉽게 구현할 수 있으며, 기존 데이터베이스 모델과의 연동도 가능하다. Grails는 Java 및 Groovy 개발자뿐만 아니라, 높은 생산성을 원하는 개발자에게 적합하다.

2. 특징

Grails는 Java 플랫폼용 웹 프레임워크로서, 다음과 같은 목표를 가지고 개발되었다.


  • Java 플랫폼 기반 웹 프레임워크 제공
  • Hibernate, Spring 등 기존 Java 기술 재사용
  • 일관된 개발 프레임워크 및 문서 제공
  • 샘플 애플리케이션 및 완전한 개발 모드 제공


Grails는 기존 Java 웹 프레임워크와 비교하여 다음과 같은 세 가지 특징을 통해 높은 생산성을 제공한다.

  • XML 설정 불필요
  • 즉시 사용 가능한 개발 환경
  • 믹스인을 통한 기능 제공


Grails는 Hibernate 및 Spring과 같은 기존 Java 기술을 단일 인터페이스에서 재사용한다.[3][4][16] 또한, 다음과 같은 구성 요소들에 대한 문서를 제공한다.

  • 영속성 프레임워크
  • GSP (Groovy Server Pages)를 사용하는 템플릿
  • 웹 페이지 구성 요소를 만들기 위한 동적 태그 라이브러리
  • 사용자 정의 및 확장 가능한 Ajax 지원


Grails는 웹 서버 및 리소스 자동 재로드를 포함한 완전한 개발 모드를 제공하며, 프레임워크를 시연하는 샘플 애플리케이션도 제공한다.

Grails는 Java 플랫폼을 기반으로 구축되어 Java 라이브러리, 프레임워크 및 기존 코드 베이스와 쉽게 통합된다. Grails는 Hibernate ORM 프레임워크로 매핑된 클래스를 투명하게 통합하며, Hibernate를 사용하는 기존 애플리케이션도 Grails를 사용할 수 있다. Grails는 Spring IoC 프레임워크를 사용하며, 내부적으로 Spring MVC 애플리케이션이다.

2. 1. 높은 생산성

Grails는 기존의 Java 웹 프레임워크와 달리 높은 생산성을 제공하기 위해 다음과 같은 세 가지 특징을 가지고 있다.

  • XML 설정 불필요
  • 즉시 사용 가능한 개발 환경
  • 믹스인을 통한 기능 제공


Grails는 Java 플랫폼의 고생산성 웹 프레임워크를 목표로 개발되었다. Hibernate나 Spring Framework와 같이 이미 널리 사용되는 Java 기술을 단순하고 일관된 인터페이스로 재사용하며, 일관성 있고 배우기 쉬운 프레임워크를 지향한다. 또한 프레임워크 구성 요소에 대해 이해하기 쉬운 문서를 제공하고, 복잡하고 일관성이 없는 분야에서도 사용자가 기대하는 것을 제공한다. 예를 들어, 강력하고 일관된 영속성 프레임워크, GSP (Groovy Server Pages)를 사용한 뷰 템플릿, 웹 페이지 컴포넌트를 쉽게 만들 수 있는 동적 태그 라이브러리, Ajax 지원 등이 있다.

Grails는 배우기 쉽고, 애플리케이션 개발과 확장이 용이하도록 설계되었으며, 일관성과 강력한 기능의 균형을 유지하는 것을 목표로 한다.

기존 자바 웹 애플리케이션 개발에서는 XML 파일을 통해 환경 및 프레임워크 설정을 분리하는 경우가 많았다. 그러나 이러한 방식은 애플리케이션이 성장함에 따라 개발자가 프레임워크 설정을 이해하고 유지하는 데 시간을 소요하게 만들어 생산성을 저하시키는 요인이 되었다.

Grails는 이러한 XML 설정 파일 수정을 불필요하게 만들었다. 대신 프레임워크가 규칙을 사용하여 애플리케이션 코드를 조사하는 방식을 채택했다. 예를 들어, `grails-app/controllers` 폴더 내에서 이름이 `Controller`로 끝나는 클래스 (예: `BookController`)는 MVC의 컨트롤러로 간주된다.

데이터베이스나 로그 설정 등은 `ConfigSlurper` 형식으로 `grails-app/conf` 폴더에 배치하여 `GrailsApplication.config`에서 읽어올 수 있다.

2. 1. 1. XML 설정 불필요 (규칙 기반 설정)

Grails는 XML 설정을 최소화한다. 대신, 프레임워크는 규칙을 사용하여 Grails 기반 애플리케이션의 코드를 검사한다. 예를 들어, `Controller`로 끝나는 클래스 이름(예: `BookController`)은 웹 컨트롤러로 간주된다. Controller|컨트롤러영어로 끝나는 클래스는 MVC의 컨트롤러로 간주되며, 별도로 뷰를 지정하지 않으면 `grails-app/views/컨트롤러명/액션명.gsp`가 된다.[1]

하지만, 설정이 전혀 없는 것은 아니며, 데이터베이스나 로그 설정 등은 `ConfigSlurper` 형식으로 `grails-app/conf` 폴더에 배치한다. 이 설정은 `GrailsApplication.config`에서 읽어올 수 있다.[1]

2. 1. 2. 즉시 사용 가능한 개발 환경

Grails는 개발자가 즉시 개발을 시작할 수 있도록 웹 서버(아파치 톰캣)와 데이터베이스(H2 데이터베이스)를 포함하는 개발 환경을 제공한다.[7] 필요한 모든 라이브러리는 Grails 배포판에 포함되어 있으며, Grails는 자바 웹 환경을 배포에 맞게 자동으로 준비한다.

`grails run-app` 명령어를 사용하여 내장 서버를 시작할 수 있는데, 이 경우 개발 모드가 되어 소스 코드 변경 사항이 자동으로 다시 로드되어 적용된다.[7] 개발 모드에서는 초기 설정이 H2 데이터베이스의 인 메모리 데이터베이스로 설정된다. 실제 운영 환경에서는 `grails war` 명령어를 사용하여 war 파일로 묶어 아파치 톰캣 등에 배포할 수 있다.[8]

2. 1. 3. 동적 메서드 (믹스인)

Grails는 믹스인을 통해 여러 클래스에 동적 메서드를 제공한다. 믹스인은 마치 기능이 프로그램에 컴파일된 것처럼 클래스에 동적으로 추가되는 메서드이다.[1]

이러한 동적 메서드를 통해 개발자는 인터페이스를 구현하거나 기본 클래스를 확장하지 않고도 작업을 수행할 수 있다. Grails는 클래스 유형에 따라 동적 메서드를 제공한다. 예를 들어, 도메인 클래스에는 저장, 삭제 및 찾기와 같은 영속성 작업을 자동화하는 메서드가 있다.[1]

2. 2. Java 플랫폼과의 통합

Grails는 Java 플랫폼을 기반으로 구축되었으므로 Java 라이브러리, 프레임워크 및 기존 코드 베이스와 매우 쉽게 통합할 수 있다. 특히 Grails는 Hibernate ORM 프레임워크로 매핑된 클래스를 투명하게 통합한다.[16] 이는 Hibernate를 사용하는 기존 애플리케이션이 코드를 다시 컴파일하거나 Hibernate 클래스를 재구성하지 않고도 Grails의 동적 지속성 메서드를 사용할 수 있음을 의미한다.

Hibernate에 매핑된 Java 클래스에 대해 스캐폴딩을 구성할 수 있으며, Grails 웹 프레임워크의 기능은 이러한 클래스와 이를 사용하는 애플리케이션에서 완전히 사용 가능하다.

Grails는 Spring IoC 프레임워크도 사용한다.[3] Grails는 내부적으로 Spring MVC 애플리케이션이며, Spring 프레임워크를 사용하여 추가 Spring 빈을 프로비저닝하고 애플리케이션의 컨텍스트에 도입할 수 있다.

3. 웹 프레임워크

Grails 웹 프레임워크는 MVC 패러다임에 따라 설계되었다. Grails는 컨트롤러와 뷰를 사용하여 웹 페이지를 구성한다. 모델(도메인 클래스)에 대한 설명은 다른 섹션에서 다룬다.

Grails 애플리케이션은 `grails create-app myapp` 명령어로 생성할 수 있다. 이 명령어는 `myapp` 디렉터리 아래에 Grails 애플리케이션에 필요한 디렉터리 구조와 라이브러리 템플릿을 생성한다.

3. 1. 모델-뷰-컨트롤러(MVC) 아키텍처

Grails는 MVC 패러다임에 따라 설계되었다. Grails 애플리케이션은 `grails create-app myapp` 명령어로 생성되며, 이 명령어는 `myapp` 디렉터리 아래에 필요한 디렉터리 구조와 라이브러리 템플릿을 생성한다.

3. 2. 컨트롤러

Grails는 웹 페이지의 동작을 구현하기 위해 컨트롤러를 사용한다. 다음은 컨트롤러의 예시이다.

```groovy

class BookController {

def list() {

[ books: Book.list() ]

}

}

```

위의 컨트롤러는 `list` 액션을 가지고 있으며, 이 액션은 데이터베이스에 있는 모든 책을 포함하는 모델을 반환한다.[9] 이 컨트롤러를 생성하기 위해 다음과 같이 `grails` 명령어를 사용한다.

```bash

grails create-controller Book

```

이 명령어는 Grails 프로젝트의 `grails-app/controller` 디렉토리에 클래스를 생성한다. 컨트롤러 클래스를 생성하는 것만으로도 Grails에서 인식될 수 있다. `list` 액션은 개발 모드에서 `http://localhost:8080/book/list`에 매핑된다.

다음은 컨트롤러에서 XML이나 JSON형식으로 반환하는 예시이다.

```groovy

import grails.converters.*

class BookController {

def json() {

render Book.list() as JSON

}

}

3. 3. 뷰

Grails는 MVC 디자인 패턴을 따르며, 여기서 뷰는 사용자 인터페이스를 담당한다. Grails는 JSP와 GSP(Groovy Server Pages)를 모두 지원한다.

GSP를 사용하면 HTML 코드 내에서 `${...}` 구문을 통해 변수나 메서드를 사용하여 동적으로 내용을 생성할 수 있다.

기본적으로 GSP는 내용을 이스케이프하지 않고 출력하지만, `grails-app/conf/Config.groovy` 파일의 `grails.views.default.codec` 설정을 `html`로 변경하면 HTML 이스케이프를 적용할 수 있다.[10]

Grails는 뷰 작성을 돕는 다양한 태그 라이브러리를 제공하며, 필요한 경우 사용자 정의 태그 라이브러리를 만들어 재사용할 수도 있다.[2]

3. 3. 1. GSP (Groovy Server Pages)

Grails는 JSP와 GSP(Groovy Server Pages)를 지원하는데, 기본적으로 GSP를 사용한다. 다음은 GSP로 작성된 뷰의 예시로, 컨트롤러가 준비한 모델 내의 책 목록을 표시한다.

```xml





저희 책들







  • ${it.title} (${it.author.name})










```

위 뷰는 Grails 프로젝트의 `grails-app/views/book/list.gsp`에 저장하는데, 이는 기본 파일명 명명 규칙인 `grails-app/views/컨트롤러명/액션명.gsp`를 따른 것이다. 이 위치에 저장하면 `BookController`와 `list` 액션에 매핑되며, 파일을 이 위치에 두는 것만으로 Grails가 이를 뷰로 인식한다.

GSP에서는 `${}` 부분에서 변수나 메서드를 사용할 수 있다. 표준 설정에서는 이스케이프되지 않고 그대로 출력되지만, `grails-app/conf/Config.groovy`의 `grails.views.default.codec`를 `html`로 설정하면 HTML 이스케이프되어 출력된다[10].

3. 3. 2. 동적 태그 라이브러리

Grails는 다양한 태그 라이브러리를 기본적으로 제공하며[2], GSP(Groovy Server Pages)와 JSP를 지원한다. 기본적으로 GSP를 사용한다. 다음은 GSP로 작성된 뷰의 예시로, 컨트롤러가 준비한 모델 내의 책 목록을 보여준다.

```xml





저희 책들







  • ${it.title} (${it.author.name})










```

이 뷰는 Grails 프로젝트의 `grails-app/views/book/list.gsp`에 저장해야 한다. 이 위치는 `BookController` 및 `list` 액션에 매핑되며, 파일을 이 위치에 두는 것만으로도 Grails에서 인식된다.

GSP에서는 `${}` 부분에서 변수나 메서드를 사용할 수 있다. 표준 설정에서는 이스케이프되지 않고 그대로 출력되지만, `grails-app/conf/Config.groovy`의 `grails.views.default.codec`를 `html`로 설정하면 HTML 이스케이프되어 출력된다.[10]

Grails는 다양한 태그 라이브러리를 제공하는 동시에, 사용자가 직접 태그 라이브러리(태그 리브)를 쉽게 만들 수도 있다.[12]

다음은 `formatDate` 태그 라이브러리의 예시이다.

```groovy

class ApplicationTagLib {

def formatDate = { attrs, body ->

out << new java.text.SimpleDateFormat(attrs.format).format(attrs.date)

}

}

```

이 `formatDate` 태그 라이브러리는 Date|데이트영어 객체를 String|문자열영어으로 변환한다. 이 태그 라이브러리는 `grails-app/taglib/ApplicationTagLib.groovy` 파일에 추가하거나, 파일명 끝을 `TagLib.groovy`로 하여 `grails-app/taglib` 디렉터리에 둔다.

다음은 GSP에서 `formatDate` 태그 라이브러리를 사용한 코드 조각이다.

```xml



```

GSP에서 동적 태그 라이브러리를 사용할 때는 import 태그를 사용할 필요가 없다. 동적 태그 라이브러리는 JSP 파일에서도 사용할 수 있지만, GSP보다 약간 작업이 더 필요하다.[13]

3. 4. Ajax 지원

Grails는 버전 2.0 이후, 기본적으로 jQuery 지원을 포함하고 있다. 또한 플러그인 등으로 OpenRico, Prototype, Yahoo! UI library[11]와 같은 Ajax 라이브러리를 지원한다. Ajax 코드와 HTML을 생성하는 기존 태그 라이브러리를 이용할 수 있다. 또한, 자체 태그 라이브러리를 생성하는 것도 용이하다.

4. 영속성

Grails는 GORM을 통해 데이터베이스 영속성을 처리한다. GORM은 개발자가 복잡한 SQL 쿼리 없이도 도메인 클래스를 통해 데이터베이스와 쉽게 상호 작용할 수 있게 해준다. Grails는 스캐폴딩을 지원하여 CRUD (생성, 읽기, 수정, 삭제) 작업을 빠르게 구현할 수 있다.

GORM은 도메인 클래스에 `save()`, `delete()`, `count()`, `find()` 등의 영속성 관련 메서드를 추가한다. 이러한 메서드들을 활용하여 데이터베이스 작업을 간편하게 처리할 수 있다. 기존 데이터베이스 모델이 있는 경우, 하이버네이트 매핑 파일을 사용하여 GORM 클래스에 매핑할 수 있다.[1]

4. 1. GORM (Grails Object Relational Mapping)

GORM(Grails Object Relational Mapping)은 Grails에서 데이터베이스에 데이터를 저장하고 관리하는 데 사용되는 OR(Object Relational) 매핑 기술이다. GORM을 사용하면 개발자는 복잡한 SQL 쿼리 없이도 도메인 클래스를 통해 데이터베이스와 쉽게 상호 작용할 수 있다.

도메인 클래스는 `grails-app/domain` 디렉토리에 저장되며, `grails create-domain-class` 명령어를 사용하여 생성할 수 있다. 예를 들어, `Book` 도메인 클래스를 생성하는 명령어는 다음과 같다.

```text

grails create-domain-class myapp.Book

```

이 명령어는 `Book` 클래스 파일을 생성하며, 코드는 다음과 같이 작성할 수 있다.

```groovy

class Book {

String title

Person author

}

```

위 코드는 `title` (책 제목)과 `author` (저자) 속성을 가진 `Book` 도메인 클래스를 정의한다. GORM은 이 도메인 클래스를 기반으로 데이터베이스 테이블을 자동으로 생성하고 관리한다.

Grails 0.3 이후 버전의 GORM은 도메인 클래스에 `id` (기본 키)와 `version` (낙관적 잠금에 사용) 속성이 명시적으로 선언되지 않아도 자동으로 추가한다. 이를 통해 개발자는 데이터베이스 테이블의 구조를 직접 관리할 필요 없이, 객체 지향적인 방식으로 데이터베이스와 상호 작용할 수 있다. GORM의 백엔드에서는 Hibernate가 사용되므로, 필요한 경우 HQL 형식으로 쿼리를 작성할 수도 있다.

4. 2. 모델 (도메인 클래스)

Grails의 도메인 모델은 GORM을 사용하여 데이터베이스에 영속화된다. 도메인 클래스는 `grails-app/domain` 디렉토리에 저장되며, `grails create-domain-class Book` 명령어를 사용하여 생성할 수 있다.

이 명령어는 도메인 클래스 이름을 요청하고 적절한 파일을 생성한다. `Book` 클래스의 코드는 다음과 같다.

```groovy

class Book {

String title

Person author

}

```

위의 도메인 클래스는 책 제목을 `String`형의 `title`, 저자를 `Person`형의 `author`로 갖는 데이터 모델을 정의하고 있다.

이 클래스를 생성하는 것만으로도 Grails가 영속성을 관리하도록 할 수 있다. Grails 0.3부터 GORM이 개선되어 id와 version 속성이 없으면 도메인 클래스에 자체적으로 추가된다. id 속성은 해당 테이블의 기본 키로 사용된다. version 속성은 낙관적 잠금에 사용된다.

GORM의 기능에 의해, Grails 애플리케이션 실행 시 이 도메인 클래스에 대응하는 `book` 테이블이 DB상에 생성되며, 이 테이블은 숫자형의 `id`, 숫자형의 `version`, 문자열형의 `title`, `person` 테이블의 `id`에 대한 외부 키인 `author_id`의 4개의 컬럼을 갖는다. Grails 애플리케이션 개발자는 SQL을 거의 의식하지 않고, 도메인 클래스의 메서드로 이러한 데이터에 대한 접근을 기술할 수 있다. (물론, 필요에 따라 GORM의 백엔드인 Hibernate가 처리 가능한 HQL 형식으로 쿼리를 발행할 수도 있다.)

4. 3. 메서드

GORM은 도메인 클래스에 영속성 작업을 수행하는 동적 메서드와 정적 메서드를 추가한다.[1] 이러한 메서드들은 클래스 및 객체의 영속성 작업에 사용된다.

GORM이 도메인 클래스에 동적으로 추가하는 메서드에 대한 자세한 내용은 동적 인스턴스 메서드 및 동적 정적 (클래스) 메서드 섹션에서 확인할 수 있다.

4. 3. 1. 동적 인스턴스 메서드

`save()` 메서드는 객체를 데이터베이스에 저장한다.



def book = new Book(title:"The Da Vinci Code", author:Author.findByName("Dan Brown"))

book.save()



`delete()` 메서드는 데이터베이스에서 객체를 삭제한다.



def book = Book.findByTitle("The Da Vinci Code")

book.delete()



`refresh()` 메서드는 데이터베이스를 기반으로 객체의 상태를 갱신한다.



def book = Book.findByTitle("The Da Vinci Code")

book.refresh()



`ident()` 메서드는 데이터베이스에서 해당 객체에 할당된 ID를 가져온다.



def book = Book.findByTitle("The Da Vinci Code")

def id = book.ident()


4. 3. 2. 동적 정적 (클래스) 메서드

`count()` 메서드는 주어진 클래스에 대한 데이터베이스의 레코드 수를 반환한다.[1]

```groovy

def bookCount = Book.count()

```

`exists()` 메서드는 주어진 식별자를 가진 객체가 데이터베이스에 존재하면 true를 반환한다.[1]

```groovy

def bookExists = Book.exists(1)

```

`find()` 메서드는 객체 쿼리 문을 기반으로 데이터베이스에서 첫 번째 객체를 반환한다.[1]

```groovy

def book = Book.find("from Book b where b.title = ?", [ 'The Da Vinci Code' ])

```

쿼리 구문은 Hibernate HQL이다.[1]

`findAll()` 메서드는 데이터베이스에 존재하는 모든 객체를 반환한다.[1]

```groovy

def books = Book.findAll()

```

`findAll()` 메서드는 객체 목록을 반환하기 위한 객체 쿼리 문을 사용할 수도 있다.[1]

```groovy

def books = Book.findAll("from Book")

```

`findBy*()` 메서드는 특정 패턴과 일치하는 데이터베이스의 첫 번째 객체를 반환한다.[1]

```groovy

def book = Book.findByTitle("The Da Vinci Code")

```

또는:[1]

```groovy

def book = Book.findByTitleLike("%Da Vinci%")

```

`findAllBy*()` 메서드는 특정 패턴과 일치하는 데이터베이스의 객체 목록을 반환한다.[1]

```groovy

def books = Book.findAllByTitleLike("The%")

```

`findWhere*()` 메서드는 명명된 매개변수 집합과 일치하는 데이터베이스의 첫 번째 객체를 반환한다.[1]

```groovy

def book = Book.findWhere(title:"The Da Vinci Code")

4. 4. 스캐폴딩

Grails는 스캐폴딩을 지원하여 CRUD 작업 (생성, 읽기, 수정, 삭제)을 지원한다. 스캐폴딩 컨트롤러를 생성하여 모든 도메인 클래스를 스캐폴딩할 수 있다.

```groovy

class BookController {

static scaffold = true

}

```

위 코드를 사용하면 `http://localhost:8080/book`에서 CRUD 작업을 수행할 수 있다. 이는 BookController가 Book 도메인 클래스와 동일한 명명 규칙을 따르기 때문이다. 특정 도메인 클래스를 스캐폴딩하려면 스캐폴드 속성에서 해당 클래스를 직접 참조하면 된다.

```groovy

class SomeController {

static scaffold = Book

}

```

현재 Grails는 연관 관계에 대한 스캐폴딩은 제공하지 않는다.

Grails는 도메인 클래스로부터 컨트롤러와 뷰를 자동 생성하는 기능을 제공하는데, 이를 스캐폴드(Scaffold)라고 부르며 정적 스캐폴드와 동적 스캐폴드 두 종류가 있다.

정적 스캐폴드를 수행하려면, 도메인 클래스 `Book`을 생성한 후 다음과 같은 명령을 실행한다.

```text

grails generate-all myapp.Book

```

이 명령은 기본적인 CRUD 조작을 모두 수행할 수 있는 템플릿을 생성한다. 여기에는 `BookController` 컨트롤러와 `list.gsp`, `create.gsp`, `edit.gsp`, `show.gsp`의 네 가지 뷰가 포함된다. 이 스캐폴드를 통해 Grails 애플리케이션 개발자는 도메인 클래스를 기술하는 것만으로 기본적인 CRUD 조작이 가능한 웹 애플리케이션 템플릿을 얻을 수 있다.

컨트롤러에 다음과 같이 기술하면 임의의 도메인 클래스를 동적으로 스캐폴드할 수도 있다.[14]

```groovy

class BookController {

static scaffold = true

}

```

동적 스캐폴드는 정적 스캐폴드처럼 파일을 생성하지 않고, `http://localhost:8080/myapp/book/`에서 CRUD 조작을 제공한다.

4. 5. 기존 데이터베이스 모델과의 연동

GORM의 영속성 메커니즘은 하이버네이트를 통해 구현된다. 따라서 기존 데이터베이스는 표준 [https://grails.github.io/grails-doc/3.2.13/guide/hibernate.html#usingHibernateXMLMappingFiles 하이버네이트 매핑] 파일을 사용하여 GORM 클래스에 매핑할 수 있다.[1]

5. 대상 사용자


  • 웹 기반 애플리케이션을 만들기 위한 통합 개발 환경을 찾는 자바 또는 그루비 개발자.
  • 자바 경험이 없지만 웹 기반 애플리케이션을 구축하기 위한 높은 생산성 환경을 찾는 개발자.

참조

[1] 웹사이트 Groovy on Rails is no more (kind of) http://grails.131238[...]
[2] 웹사이트 7.3 Tag Libraries http://grails.org/do[...]
[3] 웹사이트 Grails Documentation http://grails.org/do[...]
[4] 웹사이트 Slideshare Presentation http://www.slideshar[...] 2010-11-06
[5] 웹사이트 Dropping Groovy on Rails name http://www.nabble.co[...]
[6] 웹사이트 Groovy on Rails is no more (kind of) http://grails.131238[...]
[7] 웹사이트 run-app http://grails.org/do[...]
[8] 웹사이트 war http://grails.org/do[...]
[9] 웹사이트 7.1.1 Understanding Controllers and Actions http://grails.org/do[...]
[10] 웹사이트 4.1.1 Built in options http://grails.org/do[...]
[11] 웹사이트 Yahoo! UI library http://developer.yah[...]
[12] 웹사이트 7.3 Tag Libraries http://grails.org/do[...]
[13] 웹사이트 Dynamic Tag Libralies http://grails.codeha[...]
[14] 웹사이트 17 Scaffolding http://grails.org/do[...]
[15] 웹사이트 Domain Class Dynamic Methods & Properties http://grails.codeha[...]
[16] 웹사이트 Hibernate Integration http://grails.codeha[...]
[17] 웹인용 Dropping Groovy on Rails name http://grails.131238[...] 2019-06-12



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com