 |
|
난이도 : 초급 Scott Davis, 편집장, AboutGroovy.com
2008 년 4 월 01 일 좋은 웹 프레임워크에는 대부분 견고한 영속화(persistence) 전략이 필요합니다. Scott Davis의
Grails 마스터하기
연재 2회에서는 Grails 객체 관계 매핑(GORM: Grails Object Relational Mapping) API를 살펴봅니다. 어떤 방법으로 테이블 간 연관을 만들고, 데이터 유효성 검증을 강제하며(enforce), 관계형 데이터베이스를 변경하는 작업을 쉽게 해내는지 알아보겠습니다.
지난 달 Grails라는 새로운 웹 프레임워크를 소개하는 Grails 마스터하기
기사를 시작했다.
Grails는 관심을 분리하는 모델-뷰-컨트롤러와 설정보다 관례(convention
over configuration) 같은 최신 사례를 도입했다. Grails에 내장된 스캐폴딩 능력으로 우리는 단지 몇 분 안에 초기 웹 사이트를 구축하고 실행할 수 있다.
이번 글에서는 Grails 객체 관계 매핑 API를 사용해 영속화를 쉽게 해주는 Grails의 또 다른 영역에 집중할 것이다. 객체-관계 매퍼(ORM)가 무엇인지에 대한 설명으로 시작해, 일-대-다 관계를 만드는 방법을 알아볼 것이다. 다음으로 우리 애플리케이션이 GIGO(garbage in/garbage out) 신드롬에 전염되지 않았음을 증명하는 데이터 검증(data validation)에 대해 배울 것이다. 뒷단에서 POGO(plain old Groovy objects)를 영속화하는 방법을 미세하게 조절할 수 있게 해주는 GORM DSL(domain-specific language)을 살펴볼 것이다. 마지막으로 사용하던 관계형 데이터베이스를 또 다른 데이터베이스로 얼마나 쉽게 변경할 수 있는지 살펴볼 것이다. JDBC 드라이버가 있는 데이터베이스와 하이버네이트 다이얼렉트(Hibernate dialect)만 있으면 된다.
 |
이번 연재에 대해
Grails는 '설정보다 관례' 같은 최근 실천법과 스프링과 하이버네이트 등 친숙한 자바 개발 기술을 종합한 최신 웹 개발 프레임워크다. 그루비로 작성한 Grails는 스크립트 언어 고유의 유연성과 동적인 능력을 더하면서, 레거시 자바 코드와 자연스러운 통합(seamless integration)을 이룬다. Grails를 배운 후에 결코 이전 웹 개발 방법을 다시 할 필요가 없을 것이다.
|
|
ORM 정의
관계형 데이터베이스는 1970년대부터 매우 폭넓게 쓰여 왔으며, 아직까지도 소프트웨어 개발자들은 관계형 데이터베이스에 데이터를 효율적으로 넣고 빼내는 작업으로 인해 여전히 고심하고 있다. 오늘날 소프트웨어는 대부분 대중적인 데이터베이스가 사용하는 관계형 이론이 아닌, 객체 지향 원리에 기반을 두고 있다.
ORMs 프로그램의 모든 클래스는 데이터베이스와 애플리케이션 코드 사이에서 데이터를 주고 받는 고통을 줄여준다. 비록 완벽하지는 않지만 하이버네이트, TopLink와 JPA(Java Persistence API)는 이 문제를 해결하는 가장 대중적인 자바 API다(참고자료). 이런 문제들은 매우 지속적으로(no pun intended) 거론되어, 심지어 이를 지칭하는 object-relational impedance mismatch란 문구(catchphrase)가 따로 있을 정도다(
참고자료).
GORM은 하이버네이트를 그루비(Groovy)로 살짝 덧씌운 것이다("Gibernate"가 "GORM"보다 발음하기가 어려워 쓰이지 않는 것으로 추측한다). 이 말은 기존 하이버네이트 기법을 대부분 사용할 수 있음을 의미한다. 예를 들어, HBM 매핑 파일과 어노테이션 모두 완벽하게 지원한다. 그러나 이번 글에서는 GORM의 흥미로운 기능에 집중할 것이다.
 |
객체 지향 데이터베이스와 Grails
일부 개발자들은 근본적으로 객체를 지원하는 데이터베이스를 사용해 객체 관계 임피던스 미스매치(object-relational impedance mismatch) 이슈를 벗어나길 원한다. Ted Neward의 developerWorks 연재인
The busy Java developer's guide to db4o
는 이 주제를 잘 다루고 있으며, 실무에서 객체 지향 데이터베이스의 현실을 보여준다. 어느 엔터프라이즈 개발자가 Grails db4o 플러그인을 작성해 객체지향 데이터베이스가 준비된 기술임을 증명하면 좋겠다. 그러나 현재까지는 GORM과 전통적인 관계형 데이터베이스 사용이 Grails의 영속화 전략 중 가장 좋은 선택이다.
|
|
일 대 다 관계 만들기
POGO를 데이터베이스 테이블로 저장하는 도전을 쉽게 과소평가하는 경향이 있다. 실제로 POGO를 하나의 테이블에 매핑한 경우라면, POGO 프로퍼티가 완벽하게 테이블의 칼럼과 일치하게 되므로 이 작업은 매우 쉬울 것이다.
하지만 두 POGO 상호간에 연관을 맺는 것과 같이 POGO 사이에 복잡성이 조금씩 가미될 때, 매핑이 급격하게 어려워질 수 있다.
예를 들어, 지난 달
글에서 만들기 시작했던 여행 계획자 웹 사이트를 살펴보자.
Trip POGO가 애플리케이션에서 핵심적인 역할을 수행하고 있는 것은 놀랄 일도 아니다. 텍스트 편집기에서 grails-app/domain/Trip.groovy(Listing 1 참조)를 열어보자.
Listing 1. Trip 클래스
class Trip {
String name
String city
Date startDate
Date endDate
String purpose
String notes
}
|
Listing 1에 있는 각 속성은 Trip 테이블에 있는 필드에 완벽하며 어렵지 않게 매핑된다. 지난 글에서 Grails가 재시작될 때, 대응되는 테이블에서 자동 생성되어 grails-app/domain 디렉터리에 저장되는 POGO를 사용했던 것을 기억할 수 있다. 기본적으로 Grails는 내장된 HSQLDB 데이터베이스를 사용하지만, 이번 글 마지막에서 선호하는 관계형 데이터베이스를 사용할 수 있게 할 것이다.
자주 비행기를 타고 여행하므로
Airline 클래스(Listing 2 참조)를 제대로 한 번 만들어보자.
Listing 2. Airline 클래스
class Airline {
String name
String url
String frequentFlyer
String notes
}
|
이제 이 두 클래스를 연결하고 싶은 마음이 든다. Xyz 항공사를 이용해 시카고로 여행을 가는 일정을 짜려면, 자바 코드에 하던 것처럼 그루비에서도
Trip 클래스(Listing 3)에 Airline 프로퍼티를 추가해 표현해야 한다.
이 기술을 객체 합성(object composition, 참고자료 참조)이라 한다.
Listing 3. Trip 클래스에 Airline 프로퍼티 추가하기
class Trip {
String name
String city
...
Airline airline
}
|
위 코드는 소프트웨어 모델로는 모두 완벽하지만, 관계형 데이터베이스에서는 접근법이 약간 다르다. 테이블에 있는 모든 레코드는 주 키(primary key)라는 유일한 식별자(ID)가 있다. Trip 테이블에 airline_id 필드를 추가해 두 개의 레코드(이 경우, "Xyz 여행사" 레코드와 "시카고 여행" 레코드)를 연결할 수 있다. 이런 연관을 일-대-다 연관(one-to-many relationship)이라 하며, 한 "항공사"가 다수의 "여행"과 연관을 가질 수 있다(참고자료 등을 참조해 온라인 Grails 문서에서 일-대-일과 다-대-다 연관에 대한 예를 찾을 수 있다).
제시된 데이터베이스 스키마에는 한 가지 문제점이 있다. 성공적으로
정규화된 데이터베이스이지만(참고자료 참조), 테이블에 있는 칼럼들이 우리가 작성한 소프트웨어 모델과 동기화(sync)되지 않는다는 점이다. Airline 필드를
AirlineId 필드로 변경하면, 상세 구현(사실 데이터베이스에 POGO를 영속화는 작업)에서 결국 객체 모델을 놓쳐버리게 된다. 저자로 활동하는 Joel Spolsky는 이를 Law of Leaky
Abstractions(참고자료 참조)로 부른다.
GORM은 그루비가 이해할 수 있는 방법으로 객체 모델을 표현하도록 해줌으로써 leaky-abstract 문제를 완화하는 데 도움을 준다. 잠깐 확인을 해보겠지만, 이 작업은 보이지 않는 뒷단에서 일어나는 데이터베이스 이슈를 다루고 재설정 또한 쉽게 할 수 있다. GORM을 데이터베이스에 대한 상세한 내용을 사용자에게 숨기는 데 목적이 있는 불투명한(opaque)
추상 레이어로 보기보다는 반투명한(translucent) 레이어로 봐야 한다. GORM은 내부를 숨기면서 정확히 작업을 수행하도록 잘 살피지만, 이 행동을 입맛에 맞게 충분히 변경할 수 있다. 이 두 방법 모두 우리에게 최선의 결과를 준다.
Trip POGO에 Airline 프로퍼티를 이미 추가했다.
일-대-다 연관을 완성하려면, Listing 4처럼 Airline POGO에, hasMany 설정을 추가하자.
Listing 4. Airline에 일-대-다 연관 생성하기
class Airline {
static hasMany = [trip:Trip]
String name
String url
String frequentFlyer
String notes
}
|
static hasMany 설정은 그루비 해시 맵이다. 키는 trip이고 값은
Trip 클래스다. Airline 클래스에 일-대-다 연관을 추가 설정하고 싶다면, 대괄호 안에 키/값 쌍을 쉼표(,)로 구별한 리스트를 추가하면 된다.
 |
연속 삭제
현재 모델 표준으로는 데이터베이스에서 orphans를 수행하는 것이다. 삭제되는 Airline은 존재하지 않는 부모를 가리키는
Trip 레코드를 남길 것이다. 이 시나리오를 피하는 방법으로 일 측면(one-side)에 대응되도록 hashmap 타입
정적 필드 필드를 다 측면(many-side) 클래스에 추가할 수 있다.
|
|
이제 실제 새로운 일-대-다 연관을 확인하기 위해 grails-app/controllers에 AirlineController(Listing 5 참조)를 생성하자.
Listing 5. AirlineController 클래스
class AirlineController {
def scaffold = Airline
}
|
이전 기사에서 보았듯이, def scaffold는 Grails 실행 시에 기본적인 list(),
save(), edit() 메서드를 동적으로 생성하게 한다. 더불어 Grails는 동적으로 GSP(GroovyServer Page) 뷰를 생성한다.
TripController와
AirlineController 모두에
def scaffold가 들어 있는지 확인하자. grails generate-all을 입력해 생성된 GSP 아티팩트(artifact)가 grails-app/views에 하나라도 남아있다면, (trip과 airline 디렉터리) 모두 지우자.
이번 예에서는 Grails가 컨트롤러와 뷰 모두 동적으로 스캐폴딩하도록 한다.
이제 모델 클래스와 컨트롤러가 정해진 위치에 놓였으니, Grails를 시작하자.
grails prod run-app를 입력해 운영 모드에서 애플리케이션을 실행하자. 모든 작업이 정상으로 완료되면, 다음과 같은 반가운 환영 메시지를 볼 수 있다.
Server running. Browse to http://localhost:8080/trip-planner |
 |
포트 충돌 에러 피하기
이미 8080 포트로 운영되는 또 다른 애플리케이션이 있다면, 지난
글을 참조해 포트를 변경하자. 나는 발생할 만한 또 다른 문제를 비켜가기 위해 9090 포트로 Grails 인스턴스를 실행한다.
|
|
브라우저에서
AirlineController와
TripController로 연결되는 링크를 불 수 있다.
AirlineController
를 클릭해 그림 1처럼 Xyz 항공사에 대한 상세한 정보가 채워져 있는지 확인해 보자.
그림 1. 일-대-다 연관: 일 측면(one side)
필드 순서가 알파벳에 따라 되어 있지 않다고 걱정하지 말자. 다음 절에서 수정할 것이다!
이제 그림 2처럼 새로운 Trip을 생성하자.
Airline 콤보 박스를 확인하자.
Airline 테이블에 입력했던 모든 레코드를 여기서 볼 수 있다. 주 키가 화면에 노출된다고 걱정하지 말자. 다음 절에서 조금 더 서술적인 라벨을 추가하는 방법을 살펴볼 것이다.
그림 2. 일-대-다 연관: 다 측면(many side)
Naked 객체
우리는 뒷단에서 일어나는 테이블 생성과 앞단에서 자동으로 생성되는 뷰에 모두 영향을 주는 Airline POGO(정적 hasMany)에 힌트(hint)를 추가하는 방법을 봤다. 도메인 객체(
참고자료 참조)를 장식하는 naked
objects 패턴은 Grails에서 매우 광범위하게 쓰인다. 이 정보를 POGO에 바로 추가하므로 별도 XML 설정 파일이 필요 없게 됐다. 한 곳에 정보를 모두 두어 생산성을 높이는 효과가 있다.
예를 들어, 콤보 박스에 노출되기 쉬운 주 키를 막으려면 Listing 6에 있는 것처럼 단지 Airline 클래스에 toString을 추가하면 된다.
Listing 6. Airline 클래스에 toString 메서드 추가
class Airline {
static hasMany = [trip:Trip]
String name
String url
String frequentFlyer
String notes
String toString(){
return name
}
}
|
추가된 다음부터 Airline 클래스의 이름은 콤보 박스에서 보이는 값으로 사용된다. 그러나 여기서 정말 편리한 점은, Grails가 아직 실행 중이더라도 작업한 모든 내용을 Airline.groovy에 저장해 변경 내용을 반영한다는 것이다. 실제로 실행해 보고 싶다면, 브라우저에서 새로운
Trip을 생성하면 된다. 뷰는 동적으로 생성되므로 서버를 다시 시작할 필요 없이 적절한 뷰를 받기 전까지 텍스트 편집기와 브라우저 간에 자유롭게 이동할 수 있다.
이제 알파벳 순으로 필드 정렬 문제를 해결해 보자. 이 문제는 POGO에 또 다른 설정으로
static constraints 블록을 추가해 해결할 수 있다. Listing 7에 나온 순서대로 이 블록에 필드를 추가하자(이 제약은 테이블 칼럼 순서에 영향을 미치지 않으며 단지 뷰에만 영향을 준다).
Listing 7. Airline에 필드 정렬 변경
class Airline {
static constraints = {
name()
url()
frequentFlyer()
notes()
}
static hasMany = [trip:Trip]
String name
String url
String frequentFlyer
String notes
String toString(){
return name
}
}
|
Airline.groovy 파일에 변경 내용을 저장하고 브라우저에서 새로운 airline을 생성하자. 그림 3에서 확인할 수 있는 것처럼, 이제 Listing 7에서 정한 순서에 따라 필드들이 나오는 것을 확인할 수 있다.
그림 3. 필드 순서 커스터마이징
POGO에 필드 이름을 불필요하게 두 번 입력해 DRY 원칙을
참고자료) 위반하고 있는 것을 비난하기 전에, 필드들을 개별적인 블록으로 몰아 놓은 것은 충분히 이유가 있기 때문에 안심해도 된다. Listing 7에 나온
static constraints 블록에 중괄호는 그리 오래 이 상태로 방치하지는 않을 것이다.
데이터 검증
필드 정렬에 더해
static constraints 블록에 검증 규칙을 추가할 수 있다. 예를 들어
String 타입 필드에 길이 제한을 줄 수 있다(기본적으로는 255 글자). 또한 String 필드 값이 (이메일 주소나 URL처럼) 특정 패턴과 일치하는지 확인하게 할 수도 있다. 심지어 필드가 선택인지 필수인지도 지정할 수도 있다. 이용 가능한 검증 규칙에 대한 완전한 리스트는 Grails 온라인 문서(참고자료)를 확인해 보자..
Listing 8에서는 검증 규칙이 추가된 Airline 클래스 constraints 블록을 볼 수 있다.
Listing 8. Airline 클래스에 데이터 유효성 검증 추가하기
class Airline {
static constraints = {
name(blank:false, maxSize:100)
url(url:true)
frequentFlyer(blank:true)
notes(maxSize:1500)
}
static hasMany = [trip:Trip]
String name
String url
String frequentFlyer
String notes
String toString(){
return name
}
}
|
수정된 Airline.groovy 파일을 수정하고, 브라우저에서 새로운 airline을 생성하자. 정한 검증 규칙을 위반하면 그림 4와 같은 경고를 받게 된다.
그림 4. 유효성 검증 경고
grails-app/i18n 디렉터리에 messages.properties 파일로 경고 메시지를 커스터마이징할 수 있다. 기본 메시지가 몇몇 언어에 대해 지역화되어 있는 것을 알 수 있다(Grails가 각 클래스, 각 필드 기반으로 커스텀 메시지를 만드는 방법은 온라인 Grails 문서 유효성 검증 절을 확인하자).
Listing 8에 나온 제약 대부분은 뷰 레이어에만 영향을 미치지만, 영속화 레이어에도 영향을 미치게 할 수 있다. 예를 들어, 데이터베이스에 있는
name 칼럼 길이가 100 글자일 수 있다.
입력 필드에서 뷰의 텍스트 영역으로 바뀌는 것 외에도(필드가 255 글자보다 클 때 이렇게 된다) notes 필드가 VARCHAR 칼럼에서 TEXT, CLOB, 또는
BLOB 칼럼으로 바뀌기도 한다. 이 설정은 모두 뒷단에서 사용하는 데이터베이스 타입과 하이버네이트의 다이얼렉트에 따라 결정되며, 이제는 놀라지도 않겠지만 재정의할 수도 있다.
GORM DSL
하이버네이트가 기본적으로 사용하는 설정 방법인 HBM 매핑 파일이나 어노테이션을 재정의할 수 있다. 그러나 Grails는 naked-object 방식으로 재정의할 수 있는 또 다른 세 번째 방법을 제공한다. Listing 9처럼 간단하게 POGO에
static mapping 블록을 추가해 기본 테이블과 필드 이름을 재정의하자.
Listing 9. GORM DSL 사용하기
class Airline {
static mapping = {
table 'some_other_table_name'
columns {
name column:'airline_name'
url column:'link'
frequentFlyer column:'ff_id'
}
}
static constraints = {
name(blank:false, maxSize:100)
url(url:true)
frequentFlyer(blank:true)
notes(maxSize:1500)
}
static hasMany = [trip:Trip]
String name
String url
String frequentFlyer
String notes
String toString(){
return name
}
}
|
이 매핑 블록은 새로운 Grails 애플리케이션이 기존 레거시 테이블을 사용할 경우 특히 유용하다. 여기서는 간단한 내용만 다뤘지만, ORM DSL은 간단히 테이블과 필드 이름을 매핑해 주는 것보다 더 많은 일을 할 수 있게 해준다. 각 칼럼에 대한 기본 데이터 타입 또한 재정의할 수 있다. 주 키 생성 전략을 적용할 수도 있고 심지어 복합 주 키를 설정할 수도 있다. 또한 하이버네이트 캐시 설정을 수정할 수도 있고, 외래 키 연관을 사용하는 필드를 조절하는 등 많은 기능을 제공한다.
기억해야 할 중요한 점은 위의 모든 설정은 단지 POGO로 통합되어 있다는 점이다.
DataSource.groovy 이해하기
지금까지 살펴본 모든 설정은 개별 클래스 변경에 집중되어 있었다. 이제 조금 시야를 넓혀 더 넓은 범위의 변화에 집중해 보자. 모든 도메인 클래스가 공유하는 데이터베이스에 관련된 설정은 Listing 10에 나오는 grails-app/conf/DataSource.groovy란 일반 파일에 저장된다. 이 파일을 텍스트 편집기에 끌어 놓고 한 번 살펴보자.
Listing 10. DataSource.groovy
dataSource {
pooled = false
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
}
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='org.hibernate.cache.EhCacheProvider'
}
// environment specific settings
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
url = "jdbc:hsqldb:mem:devDB"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
}
}
} |
dataSource 블록에서는 데이터베이스 연결에 사용되는
driverClassName, username과
password를 수정할 수 있다.
hibernate 블록으로 캐시 설정을 조정할 수 있다(하이버네이트를 전문적으로 사용하지 않으면 여기서 반드시 변경할 필요는 없다). 그러나 매우 흥미로운 부분은
environments 블록이다.
이전 기사에서 Grails가 development, test, production 세 모드로 수행될 수 있음을 알아 봤다.
grails prod run-app를 입력하면 production 블록에 설정된 데이터베이스 정보를 사용하라고 Grails에 알려주게 된다. username이나
password를 환경별로 조절하고 싶으면 간단히 dataSource 블록 설정을 복사한 다음, 개별 environment 블록에 붙여 넣고, 값을 변경하면 된다. environment 블록에 있는 설정은
dataSource 블록을 재정의한다.
url 설정은 JDBC 커넥션 문자 값이다. production 모드에서는 파일 기반 데이터소스를 사용하는 HSQLDB를 사용함을 기억하자. development와
test 모드에서 HSQLDB는 메모리 내 데이터소스를 사용한다. 지난 달에 서버가 재시작되는 사이에 Trip 레코드가 남아 있길 원하면 production 모드로 실행하라고 알려줬다. 이제 어떤 방법을 사용해야
development나 test 모드에서도 똑같이 레코드를 유지할 수 있는지 알 것이다.
간단히 production에 url 설정을 복사하자.
dbCreate 값은 서로 다른 환경에서 또 다른 행동을 불러 일으키는 또 다른 이유가 된다. 또 hibernate.hbm2ddl.auto 설정에 대한 별명이며, 하이버네이트가 뒷단에서 테이블을 관리하는 방법을 설정하기도 한다.
dbCreate에 create-drop
설정은 하이버네이트가 기동할 때 테이블을 생성(create)하고 종료될 때 drop을 해준다. create로 값을 변경하면 하이버네이트는 새로 테이블을 생성하고 필요한 경우 기존 테이블을 변경하지만 재시작되는 사이에 기존 데이터를 삭제하지 않는다.
production 모드에 기본값인
update는 재시작 사이에 모든 데이터를 유지할 뿐만 아니라, 필요하면 테이블을 생성하거나 수정한다.
레거시 데이터베이스 앞 단에 Grails를 사용하는 경우, dbCreate 값을 완벽하게 주석 처리해 놓을 것을 강력히 추천한다. 주석 처리를 하면 하이버네이트가 기존 데이터베이스 스키마를 수정하지 않게 된다. 비록 데이터베이스 자체와 데이터 모델에 대해 동기화를 유지해야 하긴 하지만, 이 설정으로 허가 없이 데이터베이스 테이블을 변경한 것을 알게 된 DBA로부터 극도로 흥분해 화를 내는 이메일을 받는 것보다는 낫다.
혼자 사용하는 커스텀 환경 추가는 쉽다. 예를 들어, 기업에는 베타 프로그램이 있을 것이다. 간단하게 다른 설정과 별도 DataSource.groovy에 beta 블록을 만들자(또한 비-데이터베이스 관련 설정이 있는 grails-app/conf/Config.groovy에
environments 블록을 추가할 수도 있다). beta
모드에서 Grails를 시작하려면, grails -Dgrails.env=beta run-app를 입력하자.
데이터베이스 변경
dbCreate 설정을 사용해 하이버네이트가 테이블을 관리할 수 있도록 한다면, 새로운 데이터베이스에 대해 Grails는 신속한 세 단계 프로세스를 제공한다. 데이터베이스를 생성해 로그를 남기고, lib 디렉터리에서 JDBC 드라이버를 복사해 놓은 다음, DataSource.groovy에 설정을 변경하자.
데이터베이스와 사용자를 생성하는 명령어는 제품에 따라 매우 다양하다. DB2는 온라인 문서(
참고자료 참조)에서 단계별로 따라 할 수 있는 튜토리얼을 제공한다. 일단 데이터베이스와 사용자를 생성하고, Listing 11에 나온 것처럼 사용하는 값을 DataSource.groovy에 적용하자(이 예에서는 데이터베이스 이름이 trip이라 가정한다).
Listing 11. DataSource.groovy에 대한 DB2 설정
driverClassName = "com.ibm.db2.jcc.DB2Driver"
username = "db2admin"
password = "db2admin"
url = "jdbc:db2://localhost:50000/trip"
|
이미 MySQL이 설치되었다면 Listing 12에 나온 단계를 밟아 관리자로 들어가 trip 데이터베이스를 생성하자.
Listing 12. MySQL 데이터베이스 생성하기
$ mysql --user=root
mysql> create database trip;
mysql> use trip;
mysql> grant all on trip.* to grails@localhost identified by 'server';
mysql> flush privileges;
mysql> exit
$ mysql --user=grails -p --database=trip
|
일단 데이터베이스와 사용자를 생성했으면 Listing 13처럼 값을 사용해 DataSource.groovy 파일을 수정하자.
Listing 13. DataSource.groovy에 대한 MySQL 설정
driverClassName = "com.mysql.jdbc.Driver"
username = "grails"
password = "server"
url = "jdbc:mysql://localhost:3306/trip?autoreconnect=true"
|
데이터베이스 생성과 함께 JDBC 드라이버 JAR를 lib 디렉터리에 복사해 넣고, Datasource.groovy에 값을 반영한다. 그 다음 다시 한 번
grails run-app를 입력하자. 이제 Grails에서 HSQLDB 외에 다른 데이터베이스를 사용할 수 있게 됐다.
결론
GORM 여행을 정리해 보자. 이제 ORM이 어떤 일을 하고, 유효성 검증과 테이블 연관의 관리 방법에 대해 알게 됐고, HSQLDB를 원하는 다른 데이터베이스로 변경하는 방법에 대해 알게 됐다.
이번 연재의 다음 글에서는 웹 티어에 집중할 생각이다. GSP와 더 다양한 그루비 Taglib에 대해 배울 수 있다. GSP를 다수의 페이지에서 재사용할 수 있는 마크업 조각인
partials로 분리하는 방법을 살펴 볼 것이다. 그리고 마지막으로 스캐폴딩된 뷰에서 사용하는 기본 템플릿을 커스터마이징하는 방법을 찾아 볼 것이다.
자, 그럼 Grails 마스터하기 시간을 즐겨보자.
참고자료 교육
-
Grails 마스터하기
: Grails에 대해 더 많은 정보를 얻으려면 이번 연재를 더 읽고 함께 따라해 보자.
-
Grails: Grails 웹 사이트를 방문하자.
-
Grails Framework Reference Documentation:
Grails 바이블
-
Groovy Recipes
(Pragmatic Bookshelf, 2008년 3월): Scott Davis의 최신 책에서 그루비와 Grails에 대해 더 배워보자.
-
하이버네이트, TopLink와 JPA: 가장 대중적인 자바 객체 관계 API
-
Object-relational impedance mismatch:
객체-관계형 매핑 고유의 도전 과제
-
Object composition:
간단한 객체에서부터 좀 더 복잡한 객체로 만들어보자.
-
Database normalization:
데이터 이형(data anomalies)를 피하게 해주는 관계형 데이터베이스 테이블 설계 기술
-
Leaky abstraction:
Joel Spolsky에 따르면, "정도 차이는 있지만, 평범하지 않은 추상화는 전부 새기 쉬운 추상화가 된다."
-
Naked objects: 도메인 객체를 장식(decorate)하는 아키텍처 패턴에 대해 알아보자.
-
DRY: 정보 중복의 해악을 강조하는 프로세스 원칙
- "Hello World: Learn the basic features and concepts of DB2 for Linux, UNIX, and Windows"
(developerWorks, 2006년 12월): 리눅스, 유닉스, 윈도우에서 DB2에 대한 기초적인 튜토리얼로, 데모와 hello world 예제를 포함해 함께 간단히 살펴보자.
-
Practically Groovy
: 이 developerWorks 연재는 그루비의 실질적인 사용방법을 살펴보고, 이를 언제, 어디서 적용할 수 있는지 안내해준다.
-
그루비: 프로젝트 웹 사이트에서 그루비에 대해 더 배워보자.
-
AboutGroovy.com: 최신 그루비 뉴스와 관련 글 링크가 있다.
-
모델-뷰-컨트롤러(Model-View-Controller): Grails가 준수하는 대중적인 아키텍처 패턴
-
기술 서적 서점: Grails와 관련된 책과 기술적인 주제를 찾아보자.
-
한국 developerWorks 자바 기술 존:
자바 프로그래밍의 다양한 측면에 대해 작성된 수많은 기사를 찾아 볼 수 있다.
제품 및 기술 얻기
-
DB2: 9.5 데이터 서버의 테스트 드라이버를 다운로드하자.
-
Grails: 최신 Grails를 다운로드하자
토론
필자소개  | 
|  | Scott Davis는 국제적으로 유명한 저자이자 강사, 소프트웨어 개발자다. 저서로는 Groovy Recipes: Greasing the Wheels of Java, GIS for Web Developers: Adding Where to Your Application, The Google Maps API, JBoss At Work가 있다. |
기사에 대한 평가
 |
| 이 문서 북마킹 하기
|
|