엔터프라이즈 애플리케이션이란 대규모의 복잡한 데이터를 관리하는 애플리케이션을 말합니다. 몇백만, 몇천만의 사용자 요청을 동시에 처리하기 위해서는 서버 성능과 안정성, 보안이 매우 중요합니다.
이러한 상황에서 서버 성능, 안정성, 보안을 매우 높은 수준으로 제공하는 스프링 프레임워크가 등장했습니다.
하지만 스프링은 설정이 매우 복잡했습니다. 따라서 스프링 개발팀에서 이러한 단점을 인식하고 스프링 프레임워크를 더 빠르게 이용할 수 있도록 스프링 부트를 출시했습니다.
스프링부트로 빠르게 스프링 프로젝트를 설정할 수 있고, 스타터를 사용해 간편하게 의존성을 사용하거나 관리할 수 있습니다. 개발자가 비즈니스 로직 개발에만 집중할 수 있도록 하는 것이죠.
스프링은 필요 환경들을 수동으로 구성하지만, 스프링 부트는 스프링 코어와 스프링 MVC의 모든 기능을 자동으로 로드합니다.
스프링 애플리케이션은 일반적으로 톰캣과 같은 WAS에서 배포되는데, 스프링 부트는 WAS를 자체적으로 내장하고 있습니다. 따라서 jar
파일만 빌드하면 별도의 WAS 설정 없이 어플리케이션 실행이 가능합니다.
스프링의 주요 개념인 IoC, DI, AOP, PSA에 대해 알아보도록 하겠습니다.
IoC는 Inversion of Control의 줄임말입니다.
지금까지는 클래스 작성 후 객체를 직접 생성했지만, 제어의 역전은 외부에서 관리하는 객체를 가져와 직접 사용하는 것을 말합니다.
스프링에서는 스프링 컨테이너가 객체를 관리하고 제공합니다.
public class A {
b = new B();
}
public class A {
private B b;
}
→ 코드에서 객체 생성 X, 어디선가 받아온 객체를 b에 할당DI는 제어의 역전을 구현하기 위해 사용하는 방법으로, Dependency Injection의 줄임말입니다. 어떤 클래스가 다른 클래스에 의존한다는 뜻을 갖고 있습니다.
예를 들어 @Autowired
는 스프링 컨테이너에 있는 빈이라는 것을 주입합니다. 빈은 스프링 컨테이너에서 관리하는 객체입니다.
public class A {
// A에서 B를 주입받음
@Autowired
private B b;
}
위와 같이 작성할 수 있는 이유는 스프링 컨테이너에서 객체를 주입했기 때문입니다. 즉, 스프링 컨테이너가 B 객체를 만들어 클래스 A에 줍니다.
💡 빈과 스프링 컨테이너
스프링 컨테이너
스프링 컨테이너는 빈이 생성되고 소멸되기까지의 생명 주기를 관리합니다.
빈이란?
스프링 컨테이너가 생성하고 관리하는 객체로, 스프링은 빈을 스프링 컨테이너에 등록하기 위해 XML 설정, 애너테이션 추가 등의 여러 방법을 제공합니다.
예를 들어 MyBean이라는 클래스에@Component
애너테이션을 붙이면 해당 클래스가 빈으로 등록되어 스프링 컨테이너에서 관리합니다. 빈의 이름은 클래스 이름의 첫글자를 소문자로 바꾸어 등록됩니다.@Component public class MyBean { }
AOP는 Aspect Oriented Programming의 줄임말로, 즉 관점 지향 프로그래밍을 뜻합니다. 프로그래밍에 대한 관점을 핵심 관점, 부가 관점으로 나누어 관심 기준으로 모듈화 하는 것을 의미합니다.
예를 들어, 계좌 관리 프로그램이 있다면 핵심 관점을 계좌 이체, 고객 관리, 이자 계산 등으로, 부가 관점을 로깅, 데이터베이스 연결, 트랜젝션 등의 로직으로 둘 수 있습니다.
위와 같이 부가 관점에 해당하는 로직을 모듈화하여 핵심 관점 코드에서 분리할 수 있도록 합니다. 따라서 핵심 관점 코드에만 집중할 수 있고, 프로그램 변경과 확장에 유연해집니다.
PSA는 Portable Service Abstraction의 줄임말로, 이식 가능한 서비스 추상화를 뜻합니다. 스프링에서 제공하는 다양한 기능들을 추상화하여 개발자가 더 쉽게 사용하는 인터페이스들을 말합니다.
PSA의 대표적인 예로 클라이언트의 매핑과 클래스, 매서드의 매핑을 위한 애너테이션이 있습니다.
예를 들어, 데이트베이스 접근 기술에는 JPA, MyBatis, JDBC가 있는데, 어떤 기술을 사용하든 일관된 방식으로 데이터베이스에 접근할 수 있도록 인터페이스를 지원합니다.
또 다른 예시로, WAS를 톰캣 대신 언더토우, 네티와 같은 다른 곳에서 실행해도 기존 코드로 그대로 실행할 수 있습니다.
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "Hello, world!";
}
}
https://localhost:8080/test
접속localhost
: 127.0.0.1로, 현재 사용중인 컴퓨터8080
: 스프링 부트의 포트 번호test
: @GetMapping
애너테이션으로 매서드와 매핑할 때 스프링 부트에서 설정한 경로스프링 부트 스타터는 의존성이 모여있는 그룹으로, 필요한 기능들을 간편하게 설정할 수 있도록 도와줍니다. 스프링부트는 현재 버전에 맞는 라이브러리를 알아서 관리합니다.
스타터는 spring-boot-starter-{작업유형}
이라는 명명규칙을 따릅니다.
starter | description |
---|---|
spring-boot-starter-web | Spring MVC를 사용한 RESTful 웹 서비스를 개발할 때 필요한 의존성 모음 |
spring-boot-starter-test | 스플이 애플리케이션을 테스트를 위한 필요 의존성 모음 |
spring-boot-starter-validation | 유효성 검사를 위해 필요한 의존성 모음 |
spring-boot-starter-actuator | 모니터링을 위해 애플리케이션에서 제공하는 다양한 정보를 쉽게 제공하기 쉽게 하는 의존성 모음 |
spring-boot-starter-data-jpa | ORM을 사용하기 위한 인터페이스의 모음인 JPA를 더 쉽게 사용하기 위한 의존성 모음 |
스프링 부트는 애플리케이션이 최소한의 설정만으로도 실행되도록 여러 부분을 자동으로 구성합니다. 서버를 시작할 때 구성 파일을 읽어와 자동 설정을 합니다.
자동 설정은 META-INF
에 있는 spring.factories
파일에 담겨 있습니다.
spring=boot-autoconfigure/spring.factories
입력 → 첫 번째 파일 클릭기존에는 여러 줄의 텍스트 작성을 위해 \n
을 추가했지만 자바 17 이후 """
로 감싸 여러 줄의 텍스트 작성
# 기존의 문자열 조합 방식
String query11 = "SELECT * FROM \"items\"n" +
"WHERE \"status\" = "ON_SALE\"\n" +
"ORDER BY \"price\"'\n";
String query17 = """
SELECT * FROM "items"
WHERE "status" = "ON_SALE"
ORDER BY "price"
""";
formatted()
메서드값을 파싱하기 위한 formatted() 메서드도 제공
String tecxtBlock17 = """
{
"id": %d
"name": %s,
}
""".formatted(2, "juice");
데이터 전달을 목적으로 하는 객체를 더 빠르고 간편하게 만들기 위한 기능
상속 불가능, 파라미터에 정의한 필드는 private final
로 정의
getter 자동 생성, 따라서 애너테이션이나 메서드로 getter 정의 X
record Item(String name, int price) {
// 파라미터가 private final로 정의됨
}
Item juice = new Item("juice", 3000);
juice.price(); // 3000
패턴 매칭 타입 확인을 위한 instanceof
키워드를 조금 더 쉽게 사용
// 11 버전
if (o instanceof Integer) {
Integer i = (Integer) o;
...
}
// 17 v
if (o instanceof Integer i) {
}
static double getIntegerValue(Object o) {
return switch(o) { d
case Double d -> d.intValue();
case Float f -> f.intValue();
case String s -> Integer.parseInt(s);
default -> 0d;
};
}
javax.*
→ jakarta.*
변경@SpringBootApplication
@SpringBootApplication
public class UmustbeApplication {
public static void main(String[] args) {
SpringApplication.run(UmustbeApplication.class, args);
}
}
[SpringApplication.run](http://SpringApplication.run)()
@SpringBootApplication
클래서 애너테이션 구성
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
... 생략
}
SpringBootConfiguration
: 스프링 부트 관련 설정@ComponentScan
: 사용자가 등록한 빈을 읽고 등록하는 애너테이션Component
애너테이션을 가진 클래스들을 찾아 빈으로 등록@Component
를 감싸는 애너테이션 예시@Configuration
, @Repository
, @Controller
, @RestController
, @Service
@EnableAutoConfiguration
: 자동 구성 활성화@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "Hello, world!";
}
}
→ /test GET 요청이 들어오면 test() 메서드 실행
@RestController
: 라우터 역할 (HTTP 요청과 메서드를 연결하는 장치)@RestController
는 @Controller
, @ResponseBody
애너테이션이 포함됨@Controller
애너테이션은 @Component
포함