Chapter21. 스프링 부트를 사용한 스프링 개발 간소화
스프링 부트 스타터로 프로젝트 의존성 추가하기
빈 설정 자동화
그루비와 스프링부트 CLI
그루비 컨트롤러 작성하기
그루비
- 자바가상기계(JVM) 상에서 동작하는 동적인 스크립팅 언어
- 그루비의 문법 체계는 자바의 것을 계승 발전시켰다.
- 자바에는 없는 간편 표기법(syntactic sugar)을 지원하는 외에 리스트, 맵, 정규식을 위한 구문을 제공
- 프로그래밍을 쉽고 간결하게 해줌
그루비 코드의 작성 (아래 내용 없이 그루비 코드 작성이 가능)
- 세미콜론
- public 이나 private 같은 제한자
- 프로퍼티에 대한 접근자(setter/getter) 메소드
메소드 값을 반환하기 위한 return 예약어
스타일 가이드 : http://groovy-lang.org/style-guide.html
ContactController 클래스
@Grab("thymeleaf-spring4")
@Controller
@RequestMapping("/")
class ContactController {
@Autowired
ContactRepository contactRepo
@RequestMapping(method=RequestMethod.GET)
String home(Map<String, Object> model) {
List<Contact> contacts = contactRepo.findAll()
model.putAll([contacts: contacts])
"home"
}
@RequestMapping(method=RequestMethod.POST)
String submit(Contact contact) {
contactRepo.save(contact)
"redirect:/"
}
}
import 구문에서 기본적인 몇가지 패키지와 클래스를 들여와서 작성됨
- java.io.*
- java.lang.*
- java.math.BigDecimal
- java.math.BigInteger
- java.net.*
- java.util.*
- groovy.lang.*
- groovy.util.*
@Controller, @RequestMapping, @Authwired, @RequestMethod 와 같은 스프링 타입?
- 애플리케이션이 실행될 때 스프링 부트 CLI는 그루비 컴파일러를 사용하여 그루비 클래스를 컴파일
컴파일 실패
- 자동 설정 CLI 추가 사용 : 스프링부트 스타터 의존성을 가져와서 클래스 패스에 포함해 의존성 추가함
- 그루비 컴파일에 목록에 필요한 패키지를 추가하여 코드를 다시 컴파일함
- 애플리케이션이 실행될 때 스프링 부트 CLI는 그루비 컴파일러를 사용하여 그루비 클래스를 컴파일
Contact 클래스
class Contact {
long id String firstName
String lastName
String phoneNumber
String emailAddress
}
- 세미콜론, 접근자 메소드, 제한자도 없이 작성
ContactRepository 클래스
@Grab("h2")
import java.sql.RequltSet
class ContactRepository {
@Autowired
JDBCTemplate jdbc
List<Contact> findAll() {
jdbc.query(
"select id, firstName, lastName, phoneNumber, emailAddress " +
"from contacts order by lastName",
new ReoMapper<Contact>() {
Contact mapRow(ResultSet rs, int rowNum) {
new Contact(id: rs.getLong(1), firstName: rs.getString(2),
lastName: rs.getString(3), phoneNumber: rs.getString(4),
emailAddress: rs.getString(5))
}
}
)
}
void save(Contact contact) {
jdbc.update(
jdbc.update(
"insert into contacts " +
"(firstName, lastName, phoneNumber, emailAddress) " +
"values (?, ?, ?, ?),
contact.firstName, contact.lastName, contact.phoneNumber, contact.emailAddress)
)
}
}
- 스프링부트 CLI가 자동으로 JdbcTemplate, RowMapper를 들여옴
- 자동-들여오기와 자동-해결하기로 처리 못하는 ResultSet은 명시적으로 처리
- 사용할 데이터베이스도 예상할 수 없으므로 반드시 H2데이터베이스 사용을 요청하기 위한 @Grab 애너테이션을 활용
스프링 부트 CLI 실행
자바 애플리케이션 컴파일이 끝나고 실행시킬 수 있는 방법엔 두가지가 있다.
- 커맨드라인을 이용하여 실행 가능한 JAR나 WAR 파일을 실행
- 서블릿 컨테이너로 WAR 파일을 배포
- (+) 스프링부트 CLI로 애플리케이션을 실행 (커맨드 라인 실행)
- 애플리케이션을 먼저 JAR나 WAR 파일로 먼저 빌드할 필요가 없음
- 애플리케이션 실행을 위해서 직접 그루비 소스코드를 CLI에 전달
CLI설치
Homebrew 를 사용한 수동 설치
$ brew tap pivotal/tab
$ brew install springboot
CLI로 연락처 애플리케이션 실행하기
스프링 부트 CLI로 애플리케이션을 실행하려면, spring run에 CLI를 통해 실행할 그루비 파일들을 붙여서 커맨드라인에 입력한다.
$ spring run Hello.groovy
$ spring run *.groovy
// 그루비 클래스 파일들이 여러 디렉토리에 있다면, Ant 스타일 와일드카드로 그루비 클래스를 재귀적으로 탐색함
$ spring run **/*.groovy
스프링 부트 액추에이터
액추에어터로 애플리케이션 파악하기
- 스프링 부트 액추에이터 역할
- 스프링 부트 기반의 애플리케이션에 유용한 엔드포인트 관리 기능 추가
## MAVEN
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
## GRADLE
compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
## 스프링부트 CLI
@Grab("spring-boot-starter-actuator")
Endpoint
- GET /autoconfig
- 자동 설정이 적용될 때 스프링 부트에 의한 결정을 설명
- GET /beans
- 애플리케이션을 실행하기 위해 설정되는 빈의 카탈로그
- GET /configprops
- 현재 값으로 애플리케이션의 빈을 설정하기 위한 모든 프로퍼티 목록
- GET /env
- 애플리케이션 컨텍스트에서 사용가능한 모든 환경 변수와 시스템 프로퍼티 값
- GET /env/{name}
- 특정 환경 변수나 프로퍼티 값을 표시
- GET /health
- 현재 애플리케이션의 상태 표시
- GET /info
- 애플리케이션 상세 정보
- GET /metrics
- 특정 엔드포인트에 대한 요청 개수를 포함한 애플리케이션의 메트릭 목록
- POST /shutdown
- 강제로 애플리케이션을 종료
- GET /trace
- 요청과 응답을 포함한 애플리케이션을 통해 서비스된 최근 요청에 관한 메타데이터 목록
/health Endpoint
요청
$ curl http://localhost:8080/health
응답 결과
{ "status": "UP" } { "status": "DOWN" }
/info Endpoint
application.properties
info.app.name=Spring Sample Application info.app.description=This is my first spring boot application info.app.version=1.0.0
응답 결과
{ "app" : { "version" : "1.0.0", "description" : "This is my first spring boot application", "name" : "Spring Sample Application" } }
/metrics Endpoint
publishes information about OS, JVM and Application level metrics
{ "mem" : 193024, "mem.free" : 87693, "processors" : 4, "instance.uptime" : 305027, "uptime" : 307077, "systemload.average" : 0.11, "heap.committed" : 193024, "heap.init" : 124928, "heap.used" : 105330, "heap" : 1764352, "threads.peak" : 22, "threads.daemon" : 19, "threads" : 22, "classes" : 5819, "classes.loaded" : 5819, "classes.unloaded" : 0, "gc.ps_scavenge.count" : 7, "gc.ps_scavenge.time" : 54, "gc.ps_marksweep.count" : 1, "gc.ps_marksweep.time" : 44, "httpsessions.max" : -1, "httpsessions.active" : 0, "counter.status.200.root" : 1, "gauge.response.root" : 37.0 }
Custom HealthIndicator example
@Component
public class HealthCheck implements HealthIndicator {
@Override
public Health health() {
int errorCode = check(); // perform some specific health check
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
public int check() {
// Your logic to check health
return 0;
}
}