스프링 부트의 Major 버전이 변경될 때, Spring Framework, Java 버전이 변경된다.
Major버전.Minor버전.Patch버전
@SpringBootApplication
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
@SpringBootTest
class NhnStudentServiceTest {
@Autowired
StudentService studentService;
@Test
void testGetStudents() {
// when
List<Student> actual = studentService.getStudents();
// then
Assertions.assertThat(actual).hasSize(2);
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
$ docker run --name edu-mysql -e MYSQL_ROOT_PASSWORD=test -d -p3306:3306 mysql:5.7.35 --character-set-server=utf8 --collation-server=utf8_general_ci
$ mysql -u root -p -P3306 -h 127.0.0.1
mysql> create database student_test;
sudo lsof -i:3306
sudo kill -9 {PID}
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/student_test?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.datasource.username=root
spring.datasource.password=test



$ mvn package //gradle bootjar
$ java –jar target/student-0.0.1-SNAPSHOT.jar
$ mvn spring-boot:run
$ gradle bootRun
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
bootJar {
launchScript()
}
$ sudo ln -s /var/app/student.jar /etc/init.d/student
$ service student start
[Unit]
Description=student
After=syslog.target
[Service]
User=irteam
ExecStart=/var/app/student.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
systemctl enable student.service
$ mvn spring-boot:build-image –Dspring-boot.build-image.imageName=student
$ gradle bootBuildImage --imageName=student
$ docker run –p8080:8080 student:latest
$ docker tag student:0.0.1-SNAPSHOT registry.op.internal.dooray.io/nhn-edu/student:latest
$ docker push registry.op.internal.dooray.io/nhn-edu/student:latest
$ kubectl create deployment student \
--image=registry.op.internal.dooray.io/nhn-edu/student:latest \
--dry-run=client -o yaml > student.yaml
$ kubectl apply -f student.yaml
deployment.apps/student created
$ kubectl expose deployment student --type=NodePort --name=student-service --port 8080
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head> <meta charset="utf-8"> <title>welcome</title>
</head>
<body>
<h1>Name</h1>
<h2 th:text="${student.name}"></h2>
<h1>Score</h1>
<h2 th:text="${student.score}"></h2>
</body>
</html>
@Controller
public class StudentWebController {
@GetMapping("/web/students/{id}")
public String getStudent(@PathVariable Long id,
Model model){
model.addAttribute("student", new Student("zbum", 100));
return "student";
}
}
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/main/
spring.thymeleaf.suffix=.html
<packaging>war</packaging>
<!-- JSTL for JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Need this to compile JSP -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
@SpringBootApplication
public class StudentApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(StudentApplication.class);
}
}
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>welcome</title>
</head>
<body>
<h1>JSP Sample</h1>
<h2>${message}</h2>
</body>
</html>
@Controller
public class WelcomeController {
@GetMapping("/welcome")
public String welcome(Map model) {
model.put("message", "Welcome to the world!");
return "welcome";
}
}
spring.mvc.view.prefix=WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
$ mvn clean package
$ java -jar target/student-1.0.0-SNAPSHOT.war
$ mvn spring-boot:run
@EnableWebMvc
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
//...
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
//...
}
| Stater 이름 | 설명 |
|---|---|
| spring-boot-stater-parent | spring boot 프로젝트에서 상속 받아야 할 pom |
| spring-boot-starter | Auto Configuration을 포함한 핵심 stater, loggin, yaml 지원 |
| spring-boot-stater-web | RESTful, Web 애플리케이션 구축을 위한 stater, 내장 tomcat 포함 |
| spring-boot-stater-amqp | Spring AMQP, Rabbit MQ 사용을 위한 설정 |
| spring-boot-starter-mail | Java mail을 사용하기 위한 설정, spring framework의 메일 발송기능 |
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.6</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
<properties>
<activemq.version>5.16.5</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.98</appengine-sdk.version>
<artemis.version>2.19.1</artemis.version>
<aspectj.version>1.9.7</aspectj.version>
<assertj.version>3.22.0</assertj.version>
<atomikos.version>4.0.6</atomikos.version>
<awaitility.version>4.2.0</awaitility.version>
</properties>
<dependencymanagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-web</artifactId>
<version>2.7.6</version>
</dependency>
...
</dependencies>
</dependencymanagement>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.7.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.7.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- jetty -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
@SpringBootApplication
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
@SpringBootApplication
public class StudentApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(StudentApplication.class);
application.run(args);
}
}
@SpringBootApplication
public class StudentApplication {
public static void main(String[] args) {
new SpringApplicationBuilder()
.sources(StudentConfig.class).web(WebApplicationType.NONE)
.child(FirstChildConfig.class).web(WebApplicationType.SERVLET)
.sibling(SecondChildConfig.class).web(WebApplicationType.SERVLET)
.run(args);
}
}


@SpringBootApplication(exclude= RedisAutoConfiguration.class)
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
@AutoConfiguration
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
/**
* Nested configuration if Tomcat is being used.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
public static class TomcatWebServerFactoryCustomizerConfiguration {
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment,
ServerProperties serverProperties) {
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
public static class JettyWebServerFactoryCustomizerConfiguration {
@Bean
public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment,
ServerProperties serverProperties) {
return new JettyWebServerFactoryCustomizer(environment, serverProperties);
}
}
// 생략
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Conditional {
/**
* All {@link Condition}s that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class? extends Condition[] value();
}
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
| 구분 | 내용 | 비고 |
|---|---|---|
| @ConditionalOnWebApplication | 프로젝트가 웹 애플리케이션이면 설정 동작 | - |
| @ConditionalOnBean | 해당 Bean이 Spring Context에 존재하면 동작 | Auto configuration only |
| @ConditionalOnMissingBean | 해당 Bean이 Spring Context에 존재하지 않으면 동작 | Auto configuration only |
| @ConditionalOnClass | 해당 클래스가 존재하면 자동설정 등록 | - |
| @ConditionalOnMissingClass | 해당 클래스가 존재하지 않으면 자동설정 등록 | - |
| @ConditionalOnResource | 자원이(file 등) 존재하면 동작 | - |
| @ConditionalOnProperty | 프로퍼티가 존재하면 동작 | - |
| @ConditionalOnJava | JVM 버전에 따라 동작여부 결정 | - |
| @ConditionalOnWarDeployment | 전통적인 war 배포 방식에서만 동작 | - |
| @ConditionalOnExpression | SpEL의 결과에 따라 동작여부 결정 | - |
@Configuration
public class MyAutoConfiguration {
@ConditionalOnBean
@Bean
public MyService myService() {
...
}
}
@Configuration
public class MyAutoConfiguration {
@ConditionalOnMissingBean
@Bean
public MyService myService() {
...
}
}
server.port=8888
$ SERVER_PORT=8888 java –jar target/student.jar
$ java –jar target/student.jar --server.port=8888

nhn.student.name=sangsang
nhn:
student:
name: sangsang
@Component
public class MyBean {
@Value("${nhn.student.name}")
private String name;
// ...
}
@ConfigurationProperties(”nhn.student")
public class StudentProperties {
private String name;
// getters / setters...
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
@ConfigurationProperties(”nhn-academy.student")
public class StudentProperties {
private String firstName;
// getters / setters...
}
@SpringBootApplication
@ConfigurationPropertiesScan
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
@SpringBootApplication
@EnableConfigurationProperties(value= SystemNameProperties.class)
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
spring-boot에서는 bean proxy method를 전부 기본을 false로 해놓았다.
이유는 대부분이 msa로 동작하므로 크기가 작아서 서버를 띄울 때 속도를 높이기 위해서 false로 해놓은 것이다.