이것 저것 남겨보겠습니다.
by zoooo-hs
본 글에서는 GET /hello 요청이 오면 “Hello World” 문자열을 반환하는 API 앱을 만들고 AWS Elastic Beanstalk으로 배포한다. 이를 위한 Spring Boot 프로젝트를 하나 만들고 다음과 같은 컨트롤러를 추가한다.
@RestController
public class HelloController {
@GetMapping("/hello")
public String helloWorld() {
return "Hello World";
}
}
화면 오른쪽에 주황색 새 환경 생성 버튼을 클릭한다.
웹 서버 환경 선택
애플리케이션 이름 및 환경 이름 입력
프로젝트를 bootJar로 빌드한 jar 파일 선택 후 환경 생선 클릭
환경 구성까지 어느정도 시간이 소요된 뒤 다음과 같은 화면이 나오면서 환경 구성 끝
이렇게 Spring Boot를 eb에 배포했다. 그러나 앞서 만든 GET /hello를 테스트해보면 다음과 같은 결과가 나온다.
로컬에서 이런 일이 있으면 로그를 통해 원인을 알 수 있다. eb 콘솔에서 앱의 로그를 확인할 수 있는데, 마지막 100줄 혹은 전체 로그를 확인 할 수 있다. 이번엔 마지막 100줄 결과를 보도록 한다.
eb에서 보여주는 로그는 앱의 로그와 nginx의 로그가 있다. java 플랫폼 기반 eb에서는 nginx와 jdk 환경이 갖춰진 ec2 인스턴스에 사용자의 앱 패키지를 올리는 방식으로 구성되기 때문에, http 요청에 대해서 nginx로그를 보거나 앱의 로직 오류는 앱 로그를 통해 확인 할 수 있다.
콘솔에서 로그를 보는 방법
GET /hello 요청에 502가 발생 /hello 말고도 / 에도 오류가 발생하지만, 이 부분은 뒤에서 다시 보도록 하고 일단 /hello에 대해서 좀 더 자세히 로그를 살펴보도록 한다.
http://127.0.0.1:5000/hello ?
eb에서는 기본적으로 80 포트로 온 요청을 nginx를 통해 localhost:5000 으로 리버스 프록시하고 있다. 그러나 스프링 부트 프로젝트는 기본적으로 8080 포트를 사용하여 http 요청을 listen한다. 이러한 포트 차이로 우리의 요청이 스프링 앱에 전달되지 못한 것이다. 이를 해결하는 방법은 두 가지가 있는데
1번의 경우 프로젝트 파일을 고쳐서 다시 재배포 해야 하기 때문에 2번을 통해 바꿔보도록 한다. eb의 환경 속성 중 SERVER_PORT를 설정하면 nginx에서 프록시하는 포트를 바꿀 수 있다고 한다.
콘솔에서 앱의 환경 속성을 설정하기 위해서는 다음 메뉴를 선택한다.
환경 속성에서 다음과 같이 SERVER_PORT를 설정 후 적용
환경 속성을 적용하면 앱이 재시작된다.
앱이 재시작되고 다시 요청을 보내보면 잘 응답한다.
GET /hello에 대해서는 잘 응답하지만, 여전히 로그에선 GET / 에 대해선 404 에러를 보인다. 이는 당연한 게 우리가 만든 코드에는 GET /에 대한 컨트롤러 메소드가 없기 때문이다. 우리가 직접 보낸 요청도 아닌데 왜 이렇게 많은 GET / 요청이 존재할까?
404 에러와 함께 적혀있는 ELB-HealthChecker로 알 수 있듯, 이는 eb 환경을 구축하며 함께 생성된 로드밸런서의 인스턴스 health check 기능이다. 로드밸런서에서 주기적으로 인스턴스가 살아있는지 확인하는 요청을 보내는 것이다. 200 OK 응답을 보이면 살아있다고 판단하는 것이다. 프로젝트로 돌아와 다음과 같은 코드를 추가하고, jar 패키징 후 앱을 재배포해 보자. 앱 재배포는 콘솔에서 업로드 및 배포 버튼을 눌러 다시 jar를 업로드 할 수 있다.
@RestController
public class HealthController {
@GetMapping("/")
public String healthCheck() {
return "건강합니다^^";
}
}
앱이 재시작되고 난 뒤에 상태가 기분 좋은 초록 아이콘으로 바뀌었다.
로그에서도 GET / 요청에 잘 응답하는 것을 알 수 있다.
그렇지 않다. 로드밸런서 설정에서 health check URL을 변경할 수 있다.
대상 그룹은 로드밸런서에서 부하를 전달하는 대상을 말하는데, AWS 람다, 인스턴스, IP 등이 있다. eb 환경을 생성할때 ec2 인스턴스와 해당 인스턴스를 대상 그룹으로 부하를 전달하는 로드밸런서가 생성되는데, 우리는 해당 타겟 그룹의 health check 설정을 바꿔줘야 한다.
위 그림과 같이 검색란에서 우리가 만든 환경의 이름을 입력해 필터링하고, 대상 그룹을 선택한다.
중간에 있는 탭 메뉴 중 Health Check를 선택하면 Path가 /로 지정되어 있는걸 볼 수 있다. Edit을 선택하여 편집
Path를 원하는 값으로 변경 후 적용
이제 프로젝트에서도 변경한 경로에 맞는 health check 컨트롤러 메소드로 수정한다.
@RestController
public class HealthController {
@GetMapping("/custom/health/path/you/want")
public String healthCheck() {
return "건강합니다^^";
}
}
spring boot 의존성으로 actuator를 추가할 수 있는데, 원래는 스프링 앱의 상태 모니터링 정보를 API로 제공한다. 그중에 /actuator/health와 같이 앱의 health check를 위한 API도 존재하기 때문에 위처럼 코드를 직접 작성하지 않아도 health check API를 추가할 수 있다.
// build.gradle
...
implementation 'org.springframework.boot:spring-boot-starter-actuator'
...
기본 actuator API의 prefix는 /actuator인데 아래 설정으로 원하는 prefix를 부여할 수 있다.
server.servlet.contextPath: /some/prefix
이후 대상 그룹 설정에서 변경한 path에 맞춰 health check 를 수정해주면 된다.
이렇게 Spring Boot 프로젝트를 AWS Elastic Beanstalk으로 배포하는 방법을 정리해보았다. 중간의 시행착오를 제외하면 매우 간단한 방법으로 앱을 배포하고 테스트할 수 있는 환경을 제공받는다. Elastic Beanstalk은 Spring Boot뿐만 아니라 node, python 등 여러 환경을 제공하기 때문에 추후 다른 환경의 앱을 배포할 때도 유용하게 사용할 수 있다.