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는 그루비 컴파일러를 사용하여 그루비 클래스를 컴파일

      컴파일 실패

      1. 자동 설정 CLI 추가 사용 : 스프링부트 스타터 의존성을 가져와서 클래스 패스에 포함해 의존성 추가함
      2. 그루비 컴파일에 목록에 필요한 패키지를 추가하여 코드를 다시 컴파일함
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 실행

자바 애플리케이션 컴파일이 끝나고 실행시킬 수 있는 방법엔 두가지가 있다.

  1. 커맨드라인을 이용하여 실행 가능한 JAR나 WAR 파일을 실행
  2. 서블릿 컨테이너로 WAR 파일을 배포
  3. (+) 스프링부트 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;
    }
}

results matching ""

    No results matching ""