Spring Boot와 AngualrJS를 조합한 코드 자동 생성 도구(scaffolding)

필자는 Spring을 제대로 사용해 본적은 없습니다. 한두번 프로젝트 등에서 사용해본적은 있지만 대부분 전체 기능 중의 일부만을 사용하는 정도라고 할 수 있습니다. 그래서 Spring 자체에 대한 이해도가 높지는 않습니다. 과거의 경험을 보면 Spring은 초기 프로젝트 구성하는데 손이 많이 가거나, Spring을 잘 사용하는 아키텍트가 프로젝트 구성을 해줘야 잘 사용할 수 있었던 프레임워크라는 인식이 강합니다. 물론 요즘은 많이 바뀌었겠지만 말입니다.

이런 프로젝트 초기 구성의 복잡성 때문에 크지 않은 규모의 인터넷 서비스에서는 Ruby on Rails나 Django, 최근의 Nodejs + Express 등을 많이 사용하고 있으며 조금씩 이런 가벼운 웹 환경에 밀리고 있는 느낌이었습니다. 필자 역시 현재는 Rails 로 서비스를 개발하고 있습니다.  Spring 진영에서도 이런 문제점을 인식했는지 몇 년전에 Spring Boot 라는 것을 공개했습니다.

최근 이 Spring Boot에 관심이 생겨 이것 저것 보는 중에 JHipster라는 Spring Boot와 AngularJS를 조합한 자동 코드 생성 도구를 알게 되었습니다. 이번 글에서는 JHipster를 이용하여 자동 코드 생성하는 방법과 어느 정도까지 생성해주는지에 대해서 살펴보겠습니다.

Spring Boot

Spring Boot 프로젝트 홈페이지는 Spring Boot를 다음과 같이 정의하고 있습니다.

Takes an opinionated view of building production-ready Spring applications. Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible.

정의대로 보면 Rails나 Nodejs와 같은 최근의 플랫폼들이 지양하는 방향과 같은 목표를 가지고 있다는 것을 알 수 있습니다. Spring  Boot를 이용하면 다음과 같이 간단한 코드만으로 별도의 환경설정 없이 간단한 RestAPI 를 만들 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
@EnableAutoConfiguration
public class SampleController {
    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World!";
    }
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SampleController.class, args);
    }
}

코드에서 보는 것처럼 HTTP로 서비스를 하는 기능임에도 불구하고 main()으로 시작하는 단독 프로그램입니다. 이것이 가장 마음에 드는 부분인데 Spring Boot은 Tomcat, Jetty, Undertow 등을 Servlet Container를 외부에서 실행하고 사용자가 개발한 Servlet 등을 처리하는 것이 아니라 반대로 개발자가 개발한 코드 내에서 Tomcat 등을 실행하도록 하는 구조입니다. 이런 구조의 장점은 개발 환경을 간단하게 구성할 수 있고, 배포하기에도 쉽다는 것입니다.  필자는 이런 구조를 아주 좋아합니다. Hadoop, Spark 등과 같은오픈소스 들은 이미 내부에 이런 내장 웹 서버들을 올려 운영 중에 필요한 관리 기능 등을 웹으로 제공하고 있습니다.

자바를 주 개발 언어로 사용하는 개발자로서 이런 목표를 가진 플랫폼이 나왔다는 것이 무척 반갑습니다. 최근 Rails를 사용하면서 좋았던 점도 많지만 아쉬웠던 점도 많았는데(이 내용은 다른 글로 써보려고 합니다.) Spring Boot가 이런 아쉬운 점을 해결해 줄 수 있을 것이라 기대해봅니다.

Scaffolding

scaffolding의 사전적 의미는 "공사장에서 공사 편하게 지을려고 임시적으로 만든 가설물"입니다. 이런 Scaffolding 개념이 시스템 개발에도 많이 사용되고 있습니다. 가장 잘 사용하는 플랫폼이 Ruby on Rails나 Django 등입니다. 필자가 최근 사용하고 있는 Rails에서의 scaffolding은 다음과 같이 간단한 명령만으로 실제 사용 가능한 화면까지 생성해줍니다.

1
2
3
4
5
6
# Employee scaffold로 생성
[~/workspace/rails_demo]# rails generate scaffold Employee name:string salary:integer email:string
# Employee 관련 테이블 데이터베이스에 Create 
[~/workspace/rails_demo]# rake db:migrate
# Rails 서버 실행
[~/workspace/rails_demo]# rails s

여기까지 하면 다음과 같은 파일과 화면이 만들어 집니다.

  • 테이블 생성 스크립트
  • Model 클래스
  • 목록, 상세조회, 입력, 수정, 삭제 기능을 기본적으로 제공하는 Controller 클래스 및 View
rails_scaffold

[화면] Rails scaffolding으로 생성된 화면

JHipster

https://jhipster.github.io/

이렇듯 자바 진영에서는 표준화된 scaffold 도구가 없었습니다. 하지만  Spring Boot의 출현과 JPA, Angular나 React와 같은 정형화된 화면 관련 개발 프레임워크가 출시되어 일반화되면서 이런 도구가 나올 가능성이 높아지고 있습니다. 이 글에서 소개해드릴 JHipster 도 이런 scaffolding 도구 중의 하나입니다. JHipster 로고를 보면 왠지 친숙해보이는데 가만 보니 Jenkins의 로고와 비슷한 모양입니다.

jhipster_jenkins

Rails의 경우 ActiveRecord 라는 자체 ORM이 있고, Template 엔진도 자체 제공하고 있기 때문에  Rails 자체 만으로 표준화된 Scaffold 기능을 만들기에 충분합니다. 반면 자바의 경우 다양한 ORM이 있고 Template 도구, View 구성이 있을 수 있기 때문에 Scaffold 기능을 만들기 위해서는 이중 하나를 선택해야 합니다. JHipster는 다음과 같은 조합으로 Scaffold 기능을 제공하는 솔루션입니다.

  • 기본 프레임워크: Spring Boot
  • Persistency 프레임워크(ORM): JPA
  • View: AngularJS + Bootstrap

최근 AngularJS2 가 발표되었는데 2016/10 기준으로는 아직 제공하지 않습니다.

(Updated: AngularJS2 지원은 다음 브랜치에서 개발 중

https://github.com/jhipster/generator-jhipster/blob/angular-2/NG2-GUIDE.md)

spring_boot_angular

JHipster에서 자동으로 생성해주는 기능은 다음과 같습니다.

  • 프로젝트 기본 구조
    • 디렉토리 구성, 설정 관련 xml, 빌드 관련 구성, 데이터베이스 연결 정보 등
  • Model (Entity) 클래스
  • Service 클래스
  • Repository 클래스(JPA)
  • Data Transfer Object 클래스
  • REST API Controller 클래스
  • 비즈니스 로직 처리를 위한 Service 클래스
  • AngularJS Model, Controller, Html 코드

JHipster 설치

JHipster를 설치하기 전에 먼저 Java, Git, Node.js, Bower, Yeoman,  Gulp 가 먼지 설치되어 있어야 합니다. 이 목록 중에 필자에게 낯선 솔루션이 몇개 있는데 Bower,  Yeoman, Gulp 입니다. 검색해보니 대략 다음과 같습니다.

  • Bower: 자바스크립트 라이브러리의 패키지 관리 솔루션
    • 자바스크립트도 최신 버전의 유지, 의존 관계 등이 점점 복잡해지고 있는데 이를 쉽게 관리해주는 솔루션
    • 최근에는 Webpack 에서 이 기능을 해준다고 하는데 Webpack은 또 무언인가?
  • Gulp: 자바스크립트 빌드, 패키징 도구
    • 자바스크립트에 무슨 빌드가 필요하냐라고 하겠지만 자바스크립트의 변형 문법이나 확정된 CSS 등 사용하는 경우 표준 자바스크립트, CSS 등으로 변환을 위해 컴파일이 필요하다.
    • 또한, 자바스크립트 코드 내에 whitespace 제거, 파일 합치기 등 최적화 과정도 필요하다.
  • Yeoman: Scaffolding too for modern webapps 라고 하는데 Yoeman 자체는 메인 flow를 제공하고 실제 코드를 생성하는 부분은 generator를 만들어서 붙이는 구조인 것 같습니다. 이 구현체 중의 하나가 JHipster입니다.

Java, Git, Node.js 만 별도로 설치하고 나머지 Bower, Gulp, Yeoman은 npm을 이용하여 설치할 수 있습니다. 각 솔루션 홈페이지에서 설치 방법을 확인할 수 있습니다.  JHipster 설치 방법도 홈페이지에 간단하게 나와 있으며 다음과 같이 설치합니다. 맥은 sudo로 실행합니다.

npm install -g generator-jhipster

기본 코드 생성

JHipster를 이용하여 프로젝트를 처음 생성한다면 다음 명령을 이용하여 scaffold를 생성합니다.

[~/workspace]# mkdir myfirstapp [~/workspace]# cd myfirstapp [~/workspace/myfirstapp]# yo jhipster

이 명령을 실행하면 아래와 같이 Text 기반의 Wizard가 나타납니다. 13개 항목에 대한 옵션을 선택할 수 있습니다.

jhipster_wizard

하나의 항목만 선택하는 항목인 경우 화살표로 이동한 후 엔터 키를 입력하면 되고, 여러 개의 항목을 선택하는 경우 해당 항목으로 화살표 키로 이동 후 스페이스바로 선택할 수 있습니다. 선택이 완료되면 엔터키를 입력합니다.

1
2
3
4
5
? (1/13) Which *type* of application would you like to create? (Use arrow keys)
❯ Monolithic application (recommended for simple projects)
Microservice application
Microservice gateway
[BETA] JHipster UAA server (for microservice OAuth2 authentication)

선택할 수 있는 항목은 다음과 같습니다.

  • ? (1/13) Which *type* of application would you like to create? Monolithic application (recommended for simple projects)
  • ? (2/13) What is the base name of your application? jhispter_app
  • ? (3/13) What is your default Java package name? co.kr.jaso.jhispter_sample
  • ? (4/13) Which *type* of authentication would you like to use? HTTP Session Authentication (stateful, default Spring Security mechanism)
  • ? (5/13) Which *type* of database would you like to use? SQL (H2, MySQL, MariaDB, PostgreSQL, Oracle)
  • ? (6/13) Which *production* database would you like to use? MySQL
  • ? (7/13) Which *development* database would you like to use? MySQL
  • ? (8/13) Do you want to use Hibernate 2nd level cache? Yes, with ehcache (local cache, for a single node)
  • ? (9/13) Would you like to use Maven or Gradle for building the backend? Maven?
  • (10/13) Which other technologies would you like to use? (Press <space> to select, <a> to toggle all, <i> to inverse selection)
  • ? (11/13) Would you like to use the LibSass stylesheet preprocessor for your CSS?
  • ? (12/13) Would you like to enable internationalization support?
  • ? (13/13) Which testing frameworks would you like to use?

여기까지 선택하면 자동으로 필요한 패키지를 설치합니다. 이 단계에서는  node 패키지(npm 이용)와 javascript 패키지(bower 이용) 만 설치합니다. Java 관련 패키지는 프로그램 실행 시 maven을 이용하여 자동 설치 합니다.

데이터베이스 접속 정보

이제 데이터베이스 접속 정보를 설정합니다. 'src/main/resources/config/application-dev.yml' 파일에서 데이터베이스 접속 관련 정보를 수정합니다. url에서 DB 서버의 정보 및 database  name을 입력합니다.  username, password에 데이터베이스 사용자 정보를 입력합니다.

1
2
3
4
5
6
datasource:
  type: com.zaxxer.hikari.HikariDataSource
  url: jdbc:mysql://localhost:3306/<database_name>?useUnicode=true&characterEncoding=utf8&useSSL=false
  name:
  username: root
  password:

자동으로 데이터베이스를 생성하는 옵션을 설정하지 않았거나 그런 기능이 없는 경우 DB 연결정보에서 입력한 데이터베이스를 생성합니다. 예제의 경우 MySQL을 사용하였고 데이터베이스 명은 jhipsterapp 입니다. MySQL 콘솔에서 다음 명령을 실행합니다.

mysql> create database jhipsterapp default charset 'utf8';

App 실행

App 실행은 간단합니다. 명령행에서 다음과 같이 Maven Wrapper를 실행하면 됩니다.

[~/workspace/myfirstapp]# ./mvnw

Maven Wrapper에 대한 내용은 다음 글을 참고하세요.

실행하면 다음과 같은 화면이 나타납니다.

jhispter_run

[화면] JHipster로 생성한 App 실행

jhispter_index_view

[화면] JHipster로 생성한 App 초기 화면

  • Role base 사용자 관리 기능
  • 로그인/로그아웃 기능

이 기능을 확인하기 위해서는 화면 우측 상단의 Account -> Sign in 메뉴를 선택한 다음 로그인 창에서 admin/admin 을 입력하여 로그인 합니다. 상단 메뉴가 변경되면서 "Entities", "Account", "Administration" 이 추가되어 있습니다. Entities 메뉴는 뒤에서 설명할 모델에 대해 scaffolding 화면을 이동하는 메뉴가 나타납니다.  Administration 메뉴 아래에는 서비스를 관리할 수 있는 다양한 메뉴가 있습니다.

jhispter_admin_menu

[화면] Administrator 메뉴

  • User 관리화면 Role 기반 사용자를 관리하는 기능을 제공한다. 사용자 추가, 삭제, 롤 변경 등을 할 수 있으며 여기서 생성된 사용자는 자동 생성된 Security 모듈과 연동되어 login 기능에 바로 사용할 수 있다.

jhispter_user

  • Application Metrics  화면 Application의 JVM Heap 상태, Thread 상태,  GC 상태 등을 보여주며 간단한 모니터링을 수행할 수 있는 기능을 제공한다. 전체 HTTP Request에 대해 Action 별로 Min/Max/Avg 응답시간과 히스토그램을 그릴 수 있는 정보도 같이 제공한다.

jhispter_application_metrics

  • Thread dump 화면 Application Metrics  화면에서 Threads 옆의 버튼을 클릭하면 모든 Thread 상황을 볼 수 있는 화면이 나타납니다. Thread의 Stack Trace도 볼수 있기 때문에 운영 중에는 현재 Thread의 모든 상황을 파악할 수 있기 때문에 간단하게라도 문제를 찾아 내는데 도움이 될 것 같습니다.

jhispter_thread_dump

  • Health Checks 화면 Disk와 DB이 상태 정보를 보여 줍니다.

jhispter_health_check

  • Logs 화면 Log Level을 패키지별로 설정할 수 있는 화면

jhipster_log_level

모델 Scaffolding

다음은 비즈니스 로직 수행에 필요한 모델에 대해 scaffold 생성을 해보겠습니다. 위 단계까지 수행된 상태에서 데이터베이스의 내용을 보면 다음과 같은 테이블이 자동으로 생성되어 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
mysql> use jhipsterapp;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-------------------------------+
| Tables_in_jhipsterapp        |
+-------------------------------+
| DATABASECHANGELOG             |
| DATABASECHANGELOGLOCK         |
| jhi_authority                 |
| jhi_persistent_audit_event    |
| jhi_persistent_audit_evt_data |
| jhi_persistent_token          |
| jhi_user                      |
| jhi_user_authority            |
+-------------------------------+
8 rows in set (0.00 sec)
mysql> select ID, AUTHOR, FILENAME, DESCRIPTION from DATABASECHANGELOG \G;
*************************** 1. row ***************************
 ID: 00000000000001
 AUTHOR: jhipster
 FILENAME: classpath:config/liquibase/changelog/00000000000000_initial_schema.xml
DESCRIPTION: createTable, createIndex (x2), createTable (x2), addPrimaryKey, createTable, addForeignKeyConstraint (x3), loadData, dropDefaultValue, loadData (x2), createTable (x2), addPrimaryKey, createIndex (x2), addForeignKeyConstraint
1 row in set (0.00 sec)
ERROR:
No query specified
mysql>

사용자 정보를 저장하기 위한 테이블 몇개와 DATABASECHANGELOG 라는 테이블을 볼 수 있습니다. 이 테이블은 스키마 변경 사항에 대한 로그를 관리하는 기능을 수행하게 됩니다.

JPA는 ORM이기 때문에 데이터 모델링 보다 객체 모델링을 기반으로 하여 데이터 모델링을 하게 됩니다. 따라서 JHipster는 ERD가 아닌 객체 모델을 만들고 그 정보를 이용하여 테이블을 생성하고, 관련 클래스 및 화면을 생성합니다.  모델 정의는 "JHipster Domain Language" 라는 별도 정의된 문법을 이용하여 모델에 대해 정의합니다. 직관적으로 볼 수 있는 Viewer도 제공하고 있는데 https://jhipster.github.io/jdl-studio/ 에서 확인할 수 있습니다. 샘플로 제공하는 jdl 파일은 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
entity Region {
	regionName String
}
entity Country {
	countryName String
}
// an ignored comment
/** not an ignored comment */
entity Location {
	streetAddress String,
	postalCode String,
	city String,
	stateProvince String
}
entity Department {
	departmentName String required
}
/**
 * Task entity.
 * @author The JHipster team.
 */
entity Task {
	title String,
	description String
}
/**
 * The Employee entity.
 */
entity Employee {
	/**
	* The firstname attribute.
	*/
	firstName String,
	lastName String,
	email String,
	phoneNumber String,
	hireDate ZonedDateTime,
	salary Long,
	commissionPct Long
}
entity Job {
	jobTitle String,
	minSalary Long,
	maxSalary Long
}
entity JobHistory {
	startDate ZonedDateTime,
	endDate ZonedDateTime,
	language Language
}
enum Language {
    FRENCH, ENGLISH, SPANISH
}
relationship OneToOne {
	Country{region} to Region
}
relationship OneToOne {
	Location{country} to Country
}
relationship OneToOne {
	Department{location} to Location
}
relationship ManyToMany {
	Job{task(title)} to Task{job}
}
// defining multiple OneToMany relationships with comments
relationship OneToMany {
	Employee{job} to Job,
	/**
	* A relationship
	*/
	Department{employee} to
	/**
	* Another side of the same relationship
	*/
	Employee
}
relationship ManyToOne {
	Employee{manager} to Employee
}
// defining multiple oneToOne relationships
relationship OneToOne {
	JobHistory{job} to Job,
	JobHistory{department} to Department,
	JobHistory{employee} to Employee
}
// Set pagination options
paginate JobHistory, Employee with infinite-scroll
paginate Job with pagination
dto * with mapstruct
// Set service options to all except few
service all with serviceImpl except Employee, Job
// Set an angular suffix
angularSuffix * with mySuffix

모델을 정의하기 위해 entity라는 키워드를 사용하고 모델과의 관계를 정의하기 위해 relationship OneToMany 등과 같이 정의합니다. 문법에 대한 자세한 사항은 https://jhipster.github.io/jdl/ 를 참고하세요.

이 파일을 프로젝트 디렉토리의 root에 저장한 다음 테이블 생성 및 코드 생성을 위해 다음 명령을 실행합니다.

yo jhipster:import-jdl jhipster-jdl.jh

이 명령을 실행하면 다음과 같이 생성되는 파일에 대한 로그가 나타납니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   create src/main/java/co/kr/jaso/jhispter_sample/domain/Employee.java
   create src/main/java/co/kr/jaso/jhispter_sample/repository/EmployeeRepository.java
   create src/main/java/co/kr/jaso/jhispter_sample/web/rest/EmployeeResource.java
   create src/main/java/co/kr/jaso/jhispter_sample/service/dto/EmployeeDTO.java
   create src/main/java/co/kr/jaso/jhispter_sample/service/mapper/EmployeeMapper.java
   create src/main/resources/config/liquibase/changelog/20161004045424_added_entity_Employee.xml
   create src/main/resources/config/liquibase/changelog/20161004045424_added_entity_constraints_Employee.xml
   create src/main/webapp/app/entities/employee/employees.html
   create src/main/webapp/app/entities/employee/employee-detail.html
   create src/main/webapp/app/entities/employee/employee-dialog.html
   create src/main/webapp/app/entities/employee/employee-delete-dialog.html
   create src/main/webapp/app/entities/employee/employee.state.js
   create src/main/webapp/app/entities/employee/employee.controller.js
   create src/main/webapp/app/entities/employee/employee-dialog.controller.js
   create src/main/webapp/app/entities/employee/employee-delete-dialog.controller.js
   create src/main/webapp/app/entities/employee/employee-detail.controller.js
   create src/main/webapp/app/entities/employee/employee.service.js
   create src/test/javascript/spec/app/entities/employee/employee-detail.controller.spec.js
   create src/test/java/co/kr/jaso/jhispter_sample/web/rest/EmployeeResourceIntTest.java

위 과정은 Employee 모델을 위해 자바 클래스와 화면, 이를 관리하기 위한 Controller 등의 코드를 생성하는 과정입니다. 또한, 데이터베이스의 스키마의 변경 사항도 관리할 수 있는데 liquibase 라는 Database 스키마 버전 관리 도구를 내부적으로 사용합니다. 위에서 생성되는 코드 중에  다음 두개의 파일이 스키마와 관련된 파일입니다.

create src/main/resources/config/liquibase/changelog/20161004045424_added_entity_Employee.xml create src/main/resources/config/liquibase/changelog/20161004045424_added_entity_constraints_Employee.xml

이 시점까지는 아직 테이블은 생성되지 않습니다. 단지 코드만 생성한 상태입니다.  다시 './mvnw' 명령을 이용하여 앱을 실행하면 DATABASECHANGELOG 테이블의 정보를 읽어 처리하지 않은 스키마 정보가 있으면 스키마 생성, 수정 등의 처리를 수행합니다. 앱이 실행된 다음에 테이블 정보를 확인하면 다음과 같이 테이블이 생성되어 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
mysql> show tables;
+-------------------------------+
| Tables_in_jhispterapp        |
+-------------------------------+
| DATABASECHANGELOG             |
| DATABASECHANGELOGLOCK         |
| country                       |
| department                    |
| employee                      |
| jhi_authority                 |
| jhi_persistent_audit_event    |
| jhi_persistent_audit_evt_data |
| jhi_persistent_token          |
| jhi_user                      |
| jhi_user_authority            |
| job                           |
| job_history                   |
| job_task                      |
| location                      |
| region                        |
| task                          |
+-------------------------------+
17 rows in set (0.00 sec)
mysql> select ID, AUTHOR, FILENAME, DESCRIPTION from DATABASECHANGELOG \G;
*************************** 1. row ***************************
         ID: 00000000000001
     AUTHOR: jhipster
   FILENAME: classpath:config/liquibase/changelog/00000000000000_initial_schema.xml
DESCRIPTION: createTable, createIndex (x2), createTable (x2), addPrimaryKey, createTable, addForeignKeyConstraint (x3), loadData, dropDefaultValue, loadData (x2), createTable (x2), addPrimaryKey, createIndex (x2), addForeignKeyConstraint
*************************** 2. row ***************************
         ID: 20161004045419-1
     AUTHOR: jhipster
   FILENAME: classpath:config/liquibase/changelog/20161004045419_added_entity_Region.xml
DESCRIPTION: createTable
...
*************************** 7. row ***************************
         ID: 20161004045424-1
     AUTHOR: jhipster
   FILENAME: classpath:config/liquibase/changelog/20161004045424_added_entity_Employee.xml
DESCRIPTION: createTable, dropDefaultValue
...
*************************** 15. row ***************************
         ID: 20161004045426-2
     AUTHOR: jhipster
   FILENAME: classpath:config/liquibase/changelog/20161004045426_added_entity_constraints_JobHistory.xml
DESCRIPTION: addForeignKeyConstraint (x3)
15 rows in set (0.00 sec)
ERROR:
No query specified
mysql>

이렇게 모델 관련 테이블 및 코드가 생성되었기 때문에 웹 화면에서 Admin으로 로그인 하면 Entity 메뉴에 모델의 각 Entity를 관리할 수 있는 메뉴가 나타납니다.

jhispter_entities

다음 화면은 Employee 엔티티를 관리하는 화면입니다.

  • 목록화면 컬럼을 이용하여 정렬할 수 있는 기능까지 제공한다.

jhispter_employee_list

  • 입력 및 수정화면 각 컬럼에 값을 입력할 수 있는 폼과 연관 관계가 있는 컬럼인 경우 연관 테이블에서 데이터를 읽어 선택할 수 있는 Selection 으로 제공한다. 필드가 정해진 타입에 맞지 않으면 저장 버튼이 활성화 되지 않는 등 최소한의 Validation 처리를 해주는 기능도 있다.

jhispter_employee_edit

Rails의 경우 DB와 연결된  Model의 경우 Model 클래스 내에 멤버 변수는 실제 소스 코드 내에는 없습니다. 위 예제에서 Region model은 Rails 라면 다음과 같이 생성됩니다.

1
2
3
4
5
class Region < ActiveRecord::Base
  def hello
    "Hi #{self.regionName}"
  end 
end

이렇게 자동 생성된 코드에 비즈니스 로직을 추가할 수 있습니다. hello 메소드에 보면 self.regionName 이라고 모델의 필드를 사용하고 있는제 Region 클래스에서는 정의되지 않은 필드입니다. 이것이 가능한 것은 DB 정보를 사용하고 있기 때문입니다(DB를 사용하는지 migration 정보를 이용하는지는 확인 되지 않음). 이렇게 구성하는 경우 장점은 Model의 필드(스키마)가 변경되어도 사용자가 추가한 코드를 그대로 두고 변경 사항을 자동으로 반영할 수 있다는 것입니다.

JPA 는 이런 방식으로 하지 않기 때문에 Model 에 필드 정보가 있으며 한번 생성한 다음 Model의 변경 사항을 자동으로 반영하기에는 다소 어려운 부분이 있습니다. 실제 JHipster로 이미 생성된 모델에 몇가지 로직을 추가하고, 모델에 변경사항을 입력한 다음 다시 생성하면 Conflict 발생하였다고만 표시해줍니다.

결론

지금까지 Spring-Boot, AngularJS 기반으로 기본적인 프로젝트 구성 및 각 엔티티를 입력, 수정, 삭제할 수 있는 화면까지 제공하는 코드를 생성해주는 JHipster에 대해 살펴보았습니다. 필자가 자바만 사용해오면서 최근 1년 정도 Rails 기반으로 서비스를 개발하고 있는데 Rails 를 처음 접하면서 느꼈던 점을 JHipster에서도 가능하다는 것을 보았습니다.

필자가 운영하는 서비스는 사용자가 데이터를 입력하는 것보다 서비스 운영자에 의해 관리되는 데이터가 훨씬 많습니다. 이런 관리 화면을 하나씩 개발하려면 많은 개발 리소스가 필요합니다. 이렇게 자동으로 생성된 코드를 이용하면 이런 관리용 화면 개발 비용을 줄일 수 있으며 빠르게 서비스를 만들어 나갈 수 있는 장점이 있습니다. 최근 웹 트렌드가 이런 방향으로 나가고 있는 것도 빠르게 만들어서 고객의 반응을 보고 개선해 나가기 위해서 입니다.

이런 측면에서 보면 기존의 Spring을 중심으로 한 자바 진영에서의 웹 개발 방식이 트렌드를 쫒아가지 못한다고 생각했는데 Spring-Boot가 나오면서 이를 많이 해소시켜 주고 있는 것 같습니다. 이런 방식으로 서비스를 개발하면 자바만의 장점도 충분히 활용하면서 빠르게 서비스를 만들어 나갈 수 있지 않을까 생각합니다.


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.