moon***
2023-07-23

도구 선택부터 애플리케이션 보안과 배포까지 스프링 부트의 모든 것
스프링 부트에서는 자바와 코틀린 언어 모두 사용할 수 있다. 이 책은 스프링부트에 관심이 있는 사람들에게 도움을 줄 수 있는 책으로 스프링 부트의 시작부터 개발, 디버깅, 배포, 모니터링에 이르기까지 모두 담고 있다.
- 네이티브 애플리케이션 개발 및 배포를 간소화하는 방법
- 반응형 애플리케이션을 분산 시스템으로 만드는 방법
- 개발자의 생산성과 애플리케이션의 이식성을 향상하는 아키텍처와 접근 방식
- 애플리케이션을 빠르고 안정적으로 배포하는 방법
- 애플리케이션과 시스템의 상태를 모니터링하는 방법
- 클라우드 기반 애플리케이션의 디버깅, 테스트, 보안 유지
Chapter 1. 스프링 부트
스프링 부트의 핵심 기능은 의존성 관리 간소화, 배포 간소화, 자동 설정 입니다.
1. 의존성 관리 간소화
대부분의 기본적인 의존성은 기능 구현을 위해 추가로 설정해야 하는 수많은 의존성을 포함합니다.
Rest API는 아래와 같은 의존성을 포함합니다. 특정 형식으로 응답하는 코드(JSON, XML, HTML 등), 요청된 포맷의 객체를 마샬링/언마샬링하는 코드, 요청을 처리하고 다시 응답을 반환하는 코드와 다양한 유선 프로토콜을 지원하는 코드입니다.
spring-boot-starter-web 같은 단일 스타터를 추가하면 단일 애플리케이션에 필요한 기능을 모두 제공합니다. 단일 스타터에 포함된 여러 의존성 안에 들어 있는 각 의존성 내의 여러 라이브러리 버전이 모든 의존성에 맞게 포함됩니다.
2. 배포 간소화
오래전부터 애플리케이션 서버에 자바 애플리케이션을 배포하는 과정은 복잡합니다. 스프링 부트는 번거로운 배포 프로세스의 많은 부분을 한 단계로 간소화했으며, 단일 파일을 원하는 곳까지 복사하거나 cf push 까지 진행한다고 고려하더라도, 두 단계로 줄일 수 있습니다. 모든 의존성이 포함된 단일 스프링 부트 JAR는 배포를 용이하게 합니다. 모든 의존성을 수집해 배포하는 대신 스프링 부트 플러그인이 모든 의존성 결과를 JAR 에 압축합니다. JAR가 있으면 JVM 환경에서 애플리케이션 실행이 가능합니다.
3. 자동 설정
스프링 부트는 자동 설정이 있어, 생산성을 향상시키기 때문에 개발자에게 도움을 줍니다. 스프링 부트는 ‘설정보다 관습’이라는 정신을 추구합니다. 그래서 문서화로 확립된 단순한 규칙에 따라 작업을 수행한다면, 작성해야 하는 설정 코드가 최소화되거나 아예 없어집니다.
Chapter 2. 도구 선택 및 시작
빌드 시스템, 프로그래밍 언어, 도구 모음, 코드 편집기 등 스프링 부트 애플리케이션을 만들 때 사용하는 몇 가지 옵션을 살펴봅니다. 스프링 부트 프로젝트 빌드 도구로 메이븐과 그레이들 모두 지원합니다.
1. 아파치 메이븐 vs 그레이들
메이븐은 엄격하고 때로는 독단적이기까지 한 선언적 접근법으로 프로젝트와 개발 환경을 대단히 일관되게 만듭니다. 메이븐 방식을 따르면 일반적으로 문제가 거의 발생하지 않으므로, 빌드에 신경 쓰지 않고 코드에만 집중합니다. 그레이들은 프로그래밍/스크립팅 중심입니다. 따라서 그레이들로 빌드한 프로젝트에서 새로 출시된 버전의 프로그래밍 언어를 사용하면 종종 문제가 생깁니다.
그레이들은 빌드 속도가 빠른데, 특히 대규모 프로젝트에서는 메이븐보다 훨씬 더 빠릅니다. 일반적인 마이크로서비스 프로젝트에서는 메이븐과 그레이들 빌드 속도가 비슷합니다.
2. 자바 vs 코틀린
자바는 JVM의 원래 언어이며, 코틀린은 JVM을 사용하는 비교적 새로운 언어입니다. 스프링 부트는 자바와 코틀린 모두 지원합니다. 스프링 코드가 대부분 자바를 기반으로 하므로, 스프링 부트 애플리케이션을 자바로 만들면 이점이 많습니다. 코틀린은 자바의 사용성을 개선하기 위해 만들었으며, 간결함, 안전성, 상호 운용성, 도구 친화적인 언어입니다. 코틀린은 자바와 동일한 바이트코드 출력으로 컴파일하고 자바 소스 파일과 코틀린을 모두 포함하는 스프링 프로젝트를 만들고 두 컴파일러를 쉽게 호출하기 때문에, 한 프로젝트에서도 둘 중 적합하다고 판단한 언어를 사용하면 됩니다.
Chapter 3. 첫 번째 REST API
마이크로서비스에서는 기능을 작고 응집력 있는 청크로 분할해 디커플링합니다. 따라서 더 빠른 배포와 용이한 유지보수가 가능한 유연하고 튼튼한 시스템을 구축하게 됩니다. 어떤 마이크로서비스 분산 시스템에서는 통신이 핵심입니다.
Restful API는 주로 HTTP 메서드를 기반으로 합니다.
• POST
• GET
• PUT
• PATCH
• DELETE
이는 생성(POST), 읽기(GET), 업데이트(PUT & PATCH), 삭제(DELETE)와 같이 리소스에 수행하는 일반적인 작업입니다.
GET
스프링 MVC는 뷰가 서버 렌더링된 웹페이지로 제공된다는 가정하에, 데이터와 데이터를 전송하는 부분과 데이터를 표현하는 부분을 분리해 생성합니다. 이러한 MVC 여러 부분을 연결하는 데 @Controller 어노테이션이 도움됩니다. @RestController 어노테이션은 @Controller와 @ResponseBody를 하나의 어노테이션으로 합쳐 쓴 것입니다. 결합해 하나의 어노테이션을 사용함으로써 코드를 단순하게 만들고 의도를 더욱 명확하게 표현하게 됩니다.
대부분의 애플리케이션은 프론트앤드 UI를 통해 백엔드 클라우드 리소스를 사용자에게 보여줍니다. 거의 모든 시스템의 중심 기능인 리소스 생성, 읽기, 갱신, 삭제(CRUD)를 일관된 방식으로 할 수 있습니다.
@RequestMapping 어노테이션과 HTTP 메소드와 일치하는 다양하고 편리한 어노테이션을 살펴보았습니다.
• @GetMapping
• @PostMapping
• @PutMapping
• @PatchMapping
• @DeleteMapping
Chapter 4. 데이터베이스 엑세스
스프링 부트는 개발자가 계속해서 반복적으로 수행하는 코드와 사용 패턴의 80~90%를 최대한 단순화하는 것을 목표로 합니다. 사용 패턴을 식별하면, 적절한 기본 구성을 사용해 필요한 빈을 자동으로 초기화합니다.
기존 ArrayList를 이용해 목록을 저장하고 관리했던 단일 애플리케이션 방식은 단점이 있습니다.
첫째, 회복탄력성이 떨어집니다. 애플리케이션 또는 애플리케이션이 실행중인 플랫폼에 장애가 발생하면 애플리케이션이 실행되는 동안 수행된 변경 내용이 모두 사라집니다.
둘째, 애플리케이션 규모를 확장하기 어렵습니다. 사용자가 많아져서 애플리케이션을 확장하기 위해 추가로 인스턴스를 만들어 사용하면, 새로 생긴 인스턴스는 해당 인스턴스만의 고유한 커피 목록을 가지게 됩니다. 서로 공유가 되지 않습니다.
스프링 부트 애플리케이션에서 DB에 엑세스하려면 다음 사항이 필요합니다.
• 실행중인 DB
• 프로그램상에서 DB 엑세스를 가능하게 해주는 DB Driver
• 원하는 DB에 엑세스하기 위한 스프링 데이터 모듈
Chapter 5. 애플리케이션 설정과 검사
애플리케이션은 오류가 일어나기 마련이고 대부분은 간단한 방법으로 해결이 됩니다. 그러나 문제를 정확히 해결하려면 근본원인을 파악해야 합니다.
코드 디버깅은 애플리케이션 내 동작을 구축, 식별, 분리하는 한 단계에 불과합니다. 동적이고 분산된 애플리케이션이 많아지면 다음 작업을 수행해야 합니다.
• 애플리케이션의 동적 설정과 재설정
• 현재 설정과 출처의 확인과 결정
• 애플리케이션 환경과 헬스 지표 검사와 모니터링
• 실행 중인 애플리케이션의 로깅 수준을 일시적으로 조정해 오류 원인 식별
스프링 부트는 애플리케이션의 동적 설정과 재설정을 가능케 하는 다양하고 강력한 매커니즘을 제공합니다. 심지어 애플리케이션 실행 중에도 설정과 재설정이 가능합니다.
@Value
@Value 어노테이션은 설정을 코드에 녹이는 가장 간단한 접근방식 입니다. 패턴 매칭과 SpEL(스프링 표현 언어)을 기반으로 구축되어 간단하고 강력합니다.
@ConfigurationProperties
속성을 정의하고 관련 속성을 그룹화해서, 도구로 검증 가능하고 타입 세이프한 방식으로 속성을 참조하고 사용합니다. 애플리케이션의 application.properties 파일이 보통 애플리케이션 기본값을 정의하는 데 사용되므로, 기본 지정 기능이 없어도 생각외로 유용합니다. 다양한 배포 환경에서 환경마다 다른 속성값이 필요한 경우, 속성값은 다른 소스(ex, 환경변수 or 명령 줄 매개변수)를 통해 애플리케이션 환경에 적용됩니다.
스프링 부트는 자동설정을 통해 많은 작업에서 개발자를 대행합니다. JVM의 유연성 덕분에 여러 방법 중 하나인 디버그 플래그로 자동 설정 리포트를 간단히 생성합니다. 포지티브 매치와 네가티브 매치를 보여주며 문제가 있을시 수행하지 않는 동작과 이유를 보여줍니다.
액추에이터는 무언가를 움직이게 하거나 제어하는 기계장치를 의미합니다. 스프링 부트 2.0으로 완전히 새로운 액추에이터는 수많은 주요 모니터링 시스템의 일관된 외관 메트리스를 제공하기 위해 마이크로미터 인스트루먼테이션 라이브러리를 활용하는데, 이 방식은 SLF4J의 다양한 로깅 메커니즘과 유사합니다. 이는 주어진 스프링 부트 애플리케이션 내 액추에이터를 통해 통합, 모니터링과 노출 범위를 확장합니다.
Chapter 6. 데이터 파고들기
데이터는 고려할 게 많은 복잡한 주제입니다. 가령 데이터 구조, 다른 데이터와의 관계, 데이터 처리, 저장, 조회, 데이터베이스 제공업체, 메커니즘 등을 고려해야 합니다. 어떤 형태로든 데이터가 없으면 모든 애플리케이션이 무의미합니다. 데이터를 저장하지 않고, 조회하지 않으며, 데이터를 서로 연결하지 않는 애플리케이션은 별 가치가 없습니다.
스프링 데이터는 “기본적인 데이터의 저장의 특수한 속성을 유지하면서 데이터에 엑세스하는 친숙하고 일관된 스프링 기반 프로그래밍 모델을 제공하는 것”이라고 합니다.
스프링 데이터는 다양한 복잡성(추상성) 수준에서 스프링 부트 애플리케이션이 사용할 수 있는 다양한 메커니즘과 데이터 엑세스 옵션을 제공합니다.
우선 도메인 클래스를 하나 정의한 후에 데이터 사용 범위, 클라이어느가 사용하는 외부 API, DB 종류를 고려해 데이터베이스와 추상화 수준을 정합니다. 스프링에서는 이런 작업을 할때 템플릿 or 레포지터리 중 하나를 사용합니다.
Chapter 7. 스프링 MVC로 만드는 애플리케이션
REST 상호작용, 메시지 플랫폼, 기타 통신 방법과 함께 스프링 MVC를 사용해 스프링 부트 애플리케이션을 만드는 방법을 설명하고, 템플릿 언어 지원을 소개합니다.
템플릿 엔진은 사용자의 브라우저에서 실행되고 표시될 최종 페이지를 생성하는, 이른바 서버사이드 애플리케이션을 위한 방법을 제공합니다. 뷰 기술은 기술마다 접근방식이 다르지만, 일반적으로 다음을 제공합니다.
• 예상 결과를 생성하기 위해 템플릿 엔진이 사용할 입력을 정의하는 템플릿 언어 또는 태그 모음
• 요청된 리소스를 수행할 뷰/템플릿을 결정하는 뷰 리졸버
스프링 부트가 뷰 기술을 활용하여 사용자 브라우저에 페이지를 생성하고 보여주는 방법을 소개했고, 스프링 부트가 템플릿 엔진 처리 없이 HTML과 자바스크립트를 사용해 정적 컨텐츠를 처리하는 방법도 소개했습니다. 이외에도 스프링 클라우드 스크림과 RabbitMQ를 사용해 메시징 플랫폼의 활용법과 웹소켓 연결과 핸들러 코드를 구현하였습니다.
Chapter 8. 프로젝트 리액터와 스프링 웹플럭스를 사용한 리액티브 프로그래밍
스프링 부트와 프로젝트 리액터를 활용해 SQL과 NoSQL 데이터베이스를 사용한 데이터베이스 엑세스를 구동하며, 반응 유형을 Thymeleaf 같은 뷰 기술과 통합하고, RSocket을 사용해 프로세스 간 통신을 한 차원 높은 수준으로 제고하는 방법 등을 소개합니다.
스레드 처리 수를 초과할 경우 블로킹으로 인해 응답 대기에 빠지는 경우가 발생합니다. 이를 해결하기 위해서는 전통적은 해결 방법은 더 많은 인스터스 제공이지만, 이 해결책은 스레드 압박을 해소하는 동시에 다른 문제를 야기합니다. 리액티브 프로그래밍은 이런 확장성 문제를 해결하기 위해 만들어졌습니다.
리액티브 시스템의 특징
• 응답성(Responsive)
• 회복력(Resilient)
• 탄력성(Elastic)
• 메시지 가반(Message Driven)
리액티브 스트림의 핵심요소
• API : 게시자, 구독자, 구독, 처리자
• 사양
• 구현 예제
• 기술 호환성 키트
Chapter 9. 프로덕션을 위한 애플리케이션 테스트
테스트의 다양한 측면 중 각 애플리케이션의 프로덕션 준비성을 극적으로 향상시키는 스프링 부트 애플리케이션 테스트의 기본요소를 중심으로 진행됩니다. 다룰 주네는 단위테스트, @springBootTest를 사용한 애플리케이션 전체 테스트, JUnit을 사용한 효과적인 단위 테스트 방법, 스프링 부트 슬라이스 테스트를 적용해 주제를 분리함으로써 테스트를 간소화하는 방법입니다.
단위 테스트는 코드 단위를 가능한 한 작게 분리하고 합리적으로 정의해 유효성을 검사하는 방법입니다. 테스트 결과의 개수는 코드 단위의 크기와 복잡성에 따라 기하급수적으로 늘어납니다. 단위 테스트 내 기능 수를 줄이면 단위 테스트 관리가 더 용이해집니다. 단위 테스트를 성공적으로 충분히 구현한 후에 통합 테스트, UI/UX 테스트 등을 추가해야 합니다.
테스트 클래스는 기본적으로 애플리케이션 클래스와 이름이 일치하도록 지정해 구조에 일관성을 부여합니다. 예를 들면 기본 앱 클래스의 이름이 MyApplication이면 기본 테스트 클래스는 MyApplicationTest가 됩니다. 일반적으로 테스트를 먼저 작성하고 그 테스트를 통과하도록 코드를 작성하는 테스트 주도 개발(TDD)을 권장합니다.
Chapter 10. 애플리케이션 보안
인증과 인가의 개념을 이해해야 보안 애플리케이션을 구축하고 사용자 확인과 접근 제어를 위한 기반을 마련하게 됩니다. 스프링 시큐리티는 인증과 인가를 위한 옵션을 HTTP 방화벽, 필터 체인, IETF와 W3C 표준의 광범위한 사용, 교환 옵션과 같은 메커니즘과 결합해 애플리케이션 보안성을 높입니다. 스프링 시큐리티는 바로 사용 가능한 동시에 보안을 중시하는 사고방식을 채택합니다. 부트의 강력한 자동 설정을 활용해 개발자 입력과 사용 가능한 의존성을 검증함으로써 최소한의 노력으로 스프링 부트 애플리케이션의 보안을 극대화합니다.
인증 : 어떤 것(가령 신원, 예술작품, 금융거래)을 실제, 사실 또는 진짜로 보여주는 행위, 프로세스나 방법, 무언가를 입증하는 행위나 과정
ex) 누군가 자신이 주장하는 사람임을 증명하기(신분증)
인가 : 권한을 부여하는 행위 및 수단
ex) 누군가 특정 리소스나 작업에 접근할 수 있는 확인하기
스프링 시큐리티는 OIDC(OpenID Connect)와 OAuth2를 통해 인증과 인가를 제공합니다. OAuth2는 클라우드 기반 서비스, 공유 저장소, 애플리케이션 같은 지정된 리소스에 사용자의 제3자의 인증 수단을 제공하기 위해 만들었습니다.
Chapter 11. 애플리케이션 배포
소프트웨어 개발 과정에서 배포는 애플리케이션 프로덕션으로 진입하는 단계입니다. 애플리케이션이 최종 사용자에게 약속하는 기능에 관계없이, 배포되어 해당 사용자가 실제로 애플리케이션을 사용하기 전까지는, 개발했더라도 사실상 완성품이라기보다는 습작에 가깝습니다. 애플리케이션 배포까지 진행돼야 마무리가 됩니다. 많은 개발자가 스프링 부트 애플리케이션을 WAR 파일이나 JAR 파일로 생성할 수 있다는 사실을 압니다. 대부분의 개발자는 WAR 옵션을 건너뛰고 실행가능한 JAR 파일을 생성하는 많은 이유를 알고 있으며, 그 반대의 경우는 거의 없다는 점도 잘 알고 있습니다. 많은 개발자가 깨닫지 못한 것은 스프링 부트의 ‘실행 가능한’ JAR를 빌드할 때도 다양한 요구사항과 사용 사례를 충족하는 배포 옵션이 많다는 사실입니다.
스프링 부트의 실행 가능한 JAR는 독립적이며 테스트 가능하고 배포 가능한 단일 단위로 최대의 사용성과 다양성을 제공합니다. 생성과 반복이 빠르고 환경 변화에 따라 동적으로 자체 구성 가능하며, 배포와 유지, 관리가 매우 간단합니다. 스프링 부트 JAR는 스프링 부트 메이븐과 그레이들 플러그인 덕분에 또 다른 유용한 기능이 있습니다. 바로 완전히 실행 가능한 JAR를 생성하는 기능입니다. 애플리케이션을 작동하려면 여전히 JDK가 필요합니다.
Chapter 12. 리액티브로 더 깊이 들어가기
리액티브 프로그래밍은 개발자가 분산 시스템에서 리소스를 더 잘 활용하게 하며, 심지어 강력한 확장 메커니즘을 애플리케이션 경계를 넘어 통신 채널로 확장합니다. 리액티브 프로그래밍에서 일반적으로 사용하는 선언형 접근 대신, 명시적이고 순차적인 비즈니스 로직을 사용하기 때문에 명령형 자바라 불리는 자바 개발자라면 리액티브 기능을 사용하는데 많은 수고가 따릅니다. 리액티브 스프링 부트 애플리케이션을 배포할 때 발생하는 문제를 테스트하고 진단/디버깅 하는 최신 기술을 소개하고, 운영 환경으로 전환하기 전에 웹플러스/리액터를 사용해 작업하는 방법을 살펴봅니다.
이 책은 스프링 부트에 대해 관심이 있거나 처음 시작하는 분들에게 추천해줄 수 있는 책으로, 내용이 기본 개념부터 다양한 코드 예제를 통해 많은 것을 담고 있습니다. 또한 클라우드 네이티브 애플리케이션을 구축하기 위한 프로젝트라면 이 책을 추천드립니다.
한빛미디어 <나는 리뷰어다> 활동을 위해서 책을 제공받아 작성된 서평입니다.