개발과 기록의 조화

[Spring Boot] 프로젝트 구조 본문

Web Framework/Java Spring Framework

[Spring Boot] 프로젝트 구조

dlaudtjr03 2020. 2. 1. 21:16

해당 게시물은 학습 및 기록 목적으로 작성되었습니다. 사실과 다른 내용이 있을 수 있으며, 오류가 있거나 궁금한 점은 댓글이나 dlaudtjr07@gmail.com 으로 메일 주시면 감사하겠습니다.

 

해당 게시물은 이전의 게시물과 이어집니다.

 

[Spring Boot] 프로젝트 만들기

 


스프링 부트 프로젝트 파일 구조

프로젝트 생성이 완료되었다면 , 이번엔 스프링 부트의 기본 구조를 알아도록 합시다.

 

그림-1. 프로젝트 구조

 

Spring MVC 프로젝트 구조와는 약간 다릅니다. 하나씩 짚어보도록 하겠습니다.

src/main/java

Java 클래스 파일을 모아 둔 곳입니다.

src/main/resources

xml, properties를 저장하는 곳인데, static , templates , application.properties 파일 3개가 생성되어져 있습니다. static 파일은 css , js , html등의 파일을 저장하고 , templates 는 부트에서 이용하는 타임리프(thymeleaf) 형식 템플릿 파일(jsp 아님)을 저장합니다.

 

스프링 부트에서는 jsp 파일이 아닌 thymeleaf 템플릿 엔진 사용을 권장합니다. 물론 jsp를 이용할 수는 있지만, 따로 설정을 해 주어야 합니다. 참고하시길..

application.properties

파일은 스프링 부트 전체 프로젝트의 설정을 저장하는 곳입니다. 이 파일에 설정되어져 있는 정보를 최우선적으로 따릅니다. (자바 파일에 설정되어져 있어도 이 application.properties 파일에 다른 설정이 저장되어져 있으면 의미가 없습니다)

src/test/java

경로는 JUnit 등 테스트 케이스의 자바 클래스 파일들을 저장하는 곳입니다.

om.xml은 라이브러리 의존성 파일 경로를 저장하는 파일인 것은 다들 알 것입니다. 하지만 pom.xml 에 들어가 보면,

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.ms</groupId>
	<artifactId>bootpractice</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>bootpractice</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

 

라이브러리 의존성 설정이 Lombok, DevTools를 포함해 4개만이 설정되어져 있습니다. 하지만 Maven Dependencies 에는 수십가지의 의존성이 설정되어져 있죠. pon.xml에서는 parent를 이용해 수많은 의존성 설정을 상속받을 수 있기 때문에 , 하단의 Dependency Hierarchy를 클릭하면, 1–2의 사진처럼 수많은 라이브러리 의존성 설정들이 상속되어져 있는 것을 확인할 수 있습니다.

 

그림- 2. 자식 라이브러리 의존성 파일

 


스프링 부트 어플리케이션 실행 구조

스프링 부트는 MVC 프로젝트와 다르게 메인 클래스가 존재합니다. 기본적으로 프로젝트 이름 + Application 으로 메인 클래스 하나가 생성되어져 있습니다.

 

package com.ms.practice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BootpracticeApplication {

	public static void main(String[] args) {
		SpringApplication.run(BootpracticeApplication.class, args);
	}

}

 

 

기본적으로 생성된 클래스는 기본 설정이 서버를 통한 실행으로 설정되어져 있는데 , 의존성 설정에 들어 있는 내장 톰캣을 이용해 실행합니다.

 

그림- 3. 프로젝트 실행

 

스프링 부트 프로젝트를 실행하기 위해서는 Run on Server 가아닌 Spring Boot App을 이용해 실행한다. 실행하면 콘솔 창에 약간 낯설은 화면을 볼 수 있습니다.

 

그림- 4. 웹 서버 기반 프로젝트 실행 화면

 

(스프링 실행 로고 중 역슬래시가 한글 설정이 되어져 있어서 \로 출력됩니다...)

 

스프링 부트가 내장 톰캣을 기반으로 실행되는 것을 확인 할 수 있습니다.

이 상태에서 앱을 한 번 더 실행하면 충돌이 납니다. 당연하게도 포트 설정이 8080으로 고정되어져 있기 때문인데, 이를 해결하기 위해서는 자바 어플리케이션으로 실행하는 방법이 있습니다. 우선은 메인 메소드 안에서 이를 해결해 보도록 합시다.

 

package com.ms.practice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BootpracticeApplication {

	public static void main(String[] args) {
		
		//기본 설정
		//SpringApplication.run(BootpracticeApplication.class, args);
	
		
		//자바 어플리케이션 실행 설정
		SpringApplication application = new SpringApplication(BootpracticeApplication.class);
		
		application.setWebApplicationType(WebApplicationType.NONE);
		application.run(args);
	}

}

 

application을 SpringApplication의 새로운 객체로 생성하는 방식으로 바꾸고, WebApplicationType메소드를 추가했습니다. enum속성은 WebApplicationType 이며, 값은 NONE을 호출합니다.

NONE으로 설정한다면 , 위에서 말했듯이 내장 톰캣이 아닌 일반 자바 어플리케이션으로 실행하게 됩니다.(서버 설정은 SERVLET, 스프링 5.0부터 지원하는 웹플럭스를 적용시킬 땐 REACTIVE로 설정합니다)

그림- 5. 자바 앱 기반 프로젝트 실행 화면

 

이처럼 내장 톰캣이 아닌 일반 어플리케이션으로 실행하는 것을 볼 수 있습니다.

하지만 위에 자바 코드로 설정하는 방법보다, 위쪽에서 언급한 application.properties를 이용하는 방법이 있습니다.

우선 메인 소스를 1–2–2의 코드로 바꾸고 application.properties 파일을 설정해 보도록 합시다.

 

spring.main.web-application-type=none

 

 

스프링 부트의 application.properties는 자동완성 기능을 지원합니다. 잘 써먹도록 합시다.(ctrl + space)

spring.main 프로퍼티 부분의 web-application-type 을 설정하고 값을 none으로 설정하면, 위에 자바 객체를 생성하고 메소드를 호출하는 방법이 아닌, 단 1줄로도 설정이 가능해집니다.

맨 처음에 언급했지만, application.properties 파일은 어떤 자바 클래스에 어떤 속성이 설정되어져 있어      도,application.properties에 해당 속성이 설정되어져 있으면 프로퍼티 파일의 속성이 최우선적으로 설정됩니다.

웹 서버를 이용할 경우에도 포트 설정이 간단합니다.

 

spring.main.web-application-type=servlet
server.port=8000

 

server.port로 설정해주면 끝입니다. 물론 web-application-type은 servlet으로 설정해 주어야 톰캣으로 실행됩니다. 8080이 아닌 다른 포트로도 가능하며 , 0으로 설정한다면 사용하지 않는 포트가 자동으로 랜덤하게 설정됩니다.

 

그림- 6. 웹 서버 포트 변경 화면

 

application.properties의 정보들은 (해당속성)Properties 객체에 setter메소드로 주입된다. 실제 코드는 ctrl을 누르고 해당 프로퍼티 속성을 눌러보면 확인할 수 있습니다.

 

//Import 생략
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {

//세부내용 생략

	/**
	 * Server HTTP port.
	 */
	private Integer port;

	/**
	 * Network address to which the server should bind.
	 */
	private InetAddress address;
  
  	public Integer getPort() {
		return this.port;
	}

	public void setPort(Integer port) {
		this.port = port;
	}

	public InetAddress getAddress() {
		return this.address;
	}

	public void setAddress(InetAddress address) {
		this.address = address;
	}
  
//세부내용 생략
}

 

 

해당 글은 코드프레소 DevOps Roasting 코스를 수강하면서 작성한 글입니다.

 

Comments