반응형

 

 

도서 'Spring in Action' 제 5판을 보고 책 내용과 그 이외의 부족한 부분을 채워가며 공부한 내용입니다.

 


키워드 : 스프링 애플리케이션 초기 설정, 스프링 웹 개발 방식, 스프링 MVC, Servlet


1. 스프링 애플리케이션 초기 설정

Spring Initializr

더보기

REST API를 사용하는 브라우저 기반의 웹 애플리케이션으로, 우리가 원하는 기능을 구현할 수 있는 스프링 프로젝트를 자동으로 만들어준다.

Spring Initializr를 이용하는 방법

  • 스프링 스타터
  • Intellij IDEA IDE를 사용한 새로운 프로젝트 생성
  • Spring Tool Suite IDE를 사용해서 새로운 프로젝트 생성

 

※필자는 Spring Tool Suit IDEf를 사용

 

STS를 사용해 프로젝트 생성시 폴더 구성

스프링 프로젝트의 구조

  • mvnw mvnw.cmd : 이 파일들은 메이븐 래퍼 스크립트로, 메이븐이 프로젝트를 빌드하는 데 쓰이는 파일
  • pom.xml : 메이븐이 프로젝트를 빌드할 때 필요한 정보(명세)가 들어있는 파일
  • TacoCloudApplication : 스프링 부트 메인 클래스
  • application.properties : 프로젝트의 세부적인 구성 속성을 정의할 수 있는 파일
  • static : 브라우저에 제공할 정적 콘텐츠(img, CSS, JavaScript 등)를 저장해놓는 폴더
  • templates : 브라우저에 콘텐츠를 보여주는 템플릿 파일을 두는 폴더이다.
  • TacoCloudApplicationTests.java : 스프링 애플리케이션이 성공적으로 로드되는지 확인하는 간단한 테스트 클래스

 

1. 빌드 명세(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.6.7</version> 
		<relativePath/> <!-- lookup parent from repository --> 
	</parent> 
	<groupId>sla</groupId> 
	<artifactId>taco-cloud</artifactId> 
	<version>0.0.1-SNAPSHOT</version> 
	<name>taco-cloud</name> 
	<description>Taco Cloud Example</description> 
	<properties> 
		<java.version>11</java.version> 
	</properties> 
	<dependencies> 
		<dependency> 
			<groupId>org.springframework.boot</groupId> 
			<artifactId>spring-boot-starter-thymeleaf</artifactId> 
		</dependency> 
		<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> 
		</dependency> 
	</dependencies> 
	<build> 
		<plugins> 
			<plugin> 
				<groupId>org.springframework.boot</groupId> 
				<artifactId>spring-boot-maven-plugin</artifactId> 
				<configuration> 
					<excludes> 
						<exclude> 
							<groupId>org.projectlombok</groupId> 
							<artifactId>lombok</artifactId> 
						</exclude> 
					</excludes> 
				</configuration> 
			</plugin> 
		</plugins> 
	</build> 
</project>

<parent>요소의 <version>

  • 우리 프로젝트가 부모 POM(Project Object Model)으로 spring-boot-starter-parent를 갖는다는 것을 지정
  • 이 부모 POM은 스프링 프로젝트의 여러 라이브러리의 의존성 관리를 제공
  • 스프링 부트의 버전만 기록하면 다른 라이브러리들의 버전을 지정할 필요가 없음(스프링 부트 버전에 의해 의존성 관리를 제공)

 

<dependencies>
  • 의존성 정의
  • 프로젝트 위저드에서 선택한 각 의존성이 <dependency>요소로 지정
  • Spring Web, Thymeleaf, Spring Boot DevTools, Lombok
  • spring-boot-starter-test는 우리가 테스트를 작성할 것에 대비해 스프링 Initializr가 자동으로 추가

 

<artifactId>에 포함된 starter (artifactId = 프로젝트 ID)

  • Spring Web, Thymeleaf, Test가 starter 포함
  • 스프링 부트 starter 의존성을 나타냄
    • starter 의존성
      • 우리가 필요로 하는 모든 라이브러리의 의존성을 선언하지 않아도 되므로 빌드 파일이 훨씬 작아지고 관리가 편함
      • 라이브러리의 이름이 아닌 기능의 관점으로 의존성 생각
      • 라이브러리들의 버전을 걱정하지 않아도 됨.(스프링 부트의 버전만 신경쓰면 됨)

<plugins>

  • 메이븐을 사용하는 애플리케이션을 실행
  • 의존성이 있는 모든 라이브러리가 JAR파일에 포함되어 있는지 확인
  • 런타임 시에 classpath를 찾을 수 있는지 확인
  • 메인 부트스트랩 파일(TacoCloudApplication)을 나타내는 부트스트랩 파일을 JAR파일에 생성

 

2. 애플리케이션 부트스트랩(구동)

더보기

우리가 Spring Initializr로 스프링 프로젝트를 생성하면 생기는 main 클래스를 부트스트랩 클래스

여기서는 TacoCloudApplication.java가 될 것

해당 클래스에는 @SpringBootApplication 이라는 애노테이션이 붙어있음

 

  • 부트스트랩(Bootstrap) : 한번 시작되면 알아서 진행되는 일련의 과정
  • 실행 가능 JAR파일에서 애플리케이션을 실행
  • 제일 먼저 시작되는 부트스트랩 클래스가 필요
TacoCloudApplication.java

package tacos;

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

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

@SpringBootApplication

  • @SpringBootConfiguration : 현재 클래스(TacoCloudApplication)를 구성 클래스로 지정
    • @Configuration과 거의 유사한 애노테이션이며, 다른점은 @SpringBootConfiguration은 이 클래스의 패키지와 하위패키지의 모든 @Configuration(구성 클래스)을 탐색해서 빈(객체)로 등록
  • @EnableAutoConfiguration : 스프링 부트 자동-구성을 활성화
    • 즉, @ComponentScan으로 빈이 등록된 이후, 추가적인 Bean들을 읽어 등록하는 애노테이션
    • 우리가 커스텀하게 등록한 빈 이외에 스프링이 필요로 하는 빈들을 자동으로 등록
  • @ComponentScan : 컴포넌트 검색을 활성화
    • @Component, @Controller, @Repository 등의 애노테이션이 붙어있는 클래스들을 자동으로 찾아 스프링 컨테이너에 컴포넌트로 등록
    • 따로 기본 패키지를 설정하지 않는다면, 현재 부트스트랩 패키지를 포함한 하위 패키지에 있는 컴포넌트들을 모두 빈으로 등록
    • 컴포넌트(빈) 객체로 등록하지 않을 애노테이션이나 추가적으로 등록할 커스텀 애노테이션을 추가할 수 있음
  • SpringApplication.run(TacoCloudApplication.class, args);
    • 스프링 컨테이너를 시작하고 스프링 ApplicationContext 객체를 반환

추가적인 어노테이션 정리

  • @Component : 해당 클래스가 스프링에서 객체로 만들어서 관리하는 대상임을 명시하는 어노테이션
    • @ComponentScan을 통해 @Component 어노테이션이 있는 클래스들을 객체로 생성해서 빈으로 관리
  • @Autowired : 스프링 내부에서 자신이 특정한 객체에 의존적이므로 자신에게 해당 타입의 빈을 주입해달라는 표시
    • 스프링은 @Autowired 어노테이션을 보고 스프링 내부에 관리되는 객체 중에서 적당한 것이 있는지 확인하고, 자동으로 주입
  •  @ContextConfiguration : 스프링이 실행되면서 어떤 설정 정보를 읽어 들여야 하는지 명시
    • 속성으로는 XML 파일 또는 @Configuration 어노테이션이 적용된 클래스를 지정할 수 있음.
  • @Runwith : 테스트 시 필요한 클래스를 지정
    • 스프링은 SpringJUnit4ClassRunner 클래스가 대상
  • @Test : JUnit에서 해당 메소드가 JUnit 상에서 단위 테스트의 대상임을 알려줌.

3. 웹 요청 처리(@Controller)

Controller

더보기

웹 요청과 응답을 처리하는 컴포넌트

웹브라우저 요청을 상대할 경우 컨트롤러는 선택적으로 모델데이터를 채워 응답하며 브라우저에 반환되는 HTML 을 생성하기 위해 응답의 웹요청을 뷰에 전달

 

@Controller
public class HomeController {

    @GetMapping("/") // 루트 경로 / 의 웹 요청 처리
    public String home() {
        return "home"; // 뷰 이름 반환
    }
}

※ View : src/main/resources/templates 에 html file 생성

 

4. Controller 테스트

@WebMvcTest(HomeController.class)
public class HomeControllerTest {

    @Autowired
    private MockMvc mockMvc; // MockMvc 주입

    @Test
    public void testHomepage() throws Exception {
        mockMvc.perform(get("/")) // get 수행
            .andExpect(status().isOk()) // HTTP 200 OK 리턴
            .andExpect(view().name("home")) // home.html view 
            .andExpect(content().string(containsString("Welcome to..."))); // Welcome to... 텍스트 포함
    }
}
  • 메소드 체인 적용
  • @SpringBootTest
    • 스프링 부트 기능으로 테스트를 시작하라는 것을 JUnit에 알려줌
      • JUnit : 개발자가 개발한 모듈들이 정상적으로 동작하고 원하는 결과를 만들어내는지 확인하는 테스트
    • main 메서드의 SpringApplcation.run()의 호출에 부합되는 테스트 클래스
    • 스프링 애플리케이션 컨텍스트를 로드하는 작업을 수행

 

 

2. 스프링 웹 개발 방식

1. 정적 컨텐츠 : 파일 자체를 웹 브라우저에 전달

2. MVC와 템플릿 엔진 : server에서 html 파일을 변환 후 전달

3. API : xml이나 JSON(default)으로 client에게 전달, server끼리 통신할 때 사용

 

MVC와 템플릿 엔진

 

MVC

더보기

Model, View, Controller로 관점을 3가지 형태로 나눠 프로그래밍하는 디자인 패턴

 

Model은 '어플리케이션이 무엇을 할 것인지', View는 '화면에 보여주기 위한', Controller는 '모델이 어떻게 처리할지'에 대한 역할 수행

  • Model
  • View
  • Controller

 

템플릿 엔진

더보기

DATA + Template을 가지고 Template Engine을 거쳐 Result Page가 나옴.

  • 템플릿 양식과 특정 데이터 모델에 따른 입력 자료를 합성하여 결과 문서를 출력하는 소프트웨어
  • 쉽게 말해 서버에서 동적으로 html을 변환하여 웹 브라우저로 보내주는 역할
  • 텍스트 템플릿 엔진
    • 템플릿 양식에 적절한 특정 데이터를 넣어 결과 문서를 출력(Thymeleaf, JSP)
  • 종류
    • 서버사이드 템플릿 엔진(Server Side Template Engine)
      • 서버에서 DB  혹은 API에서 가져온 데이터를 미리 정의된 Template(미리 제작된 프레임)에 넣어 html을 그려서 클라이언트에 전달
      • 즉, HTML 코드에서 고정적으로 사용하는 부분은 템플릿으로 만들어 두고 동적으로 생성되는 부분만 템플릿 소스코드에 끼워넣는 방식
    • 클라이언트 사이드 템플릿 엔진(Client Side Template Engine)
      • HTML형태로 코드를 작성할 수 있음
      • 동적으로 DOM(Document Object Model)을 그리게 해주는 역할
        • DOM - HTML 요소들의 구조화된 표현
      • 데이터를 받아 DOM 객체에 동적으로 그려주는 프로세스 담당
      • 웹페이지에서 여러 카테고리 탭 중 하나를 선택할 때 같은 형식의 프레임(template)에 내용만 바뀌어 변경되는 것

 

MVC와 템플릿 엔진의 동작과정

 

MVC와 템플릿 엔진의 동작 과정

  1. 웹 브라우저에서 localhost:8080/hi 를 요청
  2. spring boot를 띄울 때 같이 띄우는 내장 tomcat 서버를 거치면서 tomcat 서버는 /hi 요청이 왔음을 spring에게 넘김
  3. spring은 Controller에 /hi가 @GetMapping을 통해 hello-mvc가 mapping 되어 있는 것을 확인하고, mapping 되어있는 해당 메서드를 실행
    해당 메서드는 "hi-template"라는 String을 반환하고, Model에는 (key : name, value : spring)이라는 값을 넣는다. 그리고 이 값들을 spring에게 넘겨준다.
  4. spring의 viewResolver가 동작한다. viewResolver는 View를 찾아주고, 템플릿 엔진을 연결시켜주는 역할을 한다.
    viewResolver가 templates/hi-template.html 을 찾아서 Thymeleaf 템플릿 엔진에게 처리 요청을 한다.
  5. 템플릿 엔진인 Thymeleaf가 렌더링해서 html로 변환한 후, 웹 브라우저에 반환한다.

 

 

3. Servlet

더보기

자바를 사용하여 웹을 만들기 위해 필요한 기술

자바로 구현된 CGI라고 알려짐

 

※ CGI(Common Gateway Interface)

더보기

특별한 라이브러리나 도구를 의미하는 것이 아니고, 별도로 제작된 웹 서버와 프로그램간의 교환방식

 

CGI방식은 어떠한 프로그래밍 언어로도 구현이 가능하며, 별도로 만들어 놓은 프로그램에 HTML의 Get or Post 방법으로 클라이언트의 데이터를 환경변수로 전달하고, 프로그램의 표준 출력 결과를 클라이언트에게 전송하는 것

 
자바 어플리케이션 코딩을 하듯 웹 브라우저용 출력 화면을 만드는 방법

 

 

 

특징

  • 클라이언트의 요청에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트
  • html을 사용하여 요청에 응답
  • Java Thread를 이용하여 동작(서블릿 컨테이너는 멀테 쓰레드로 운용, 원래는 쓰레드의 생성을 관리해야 했지만 서블릿 컨테이너가 이를 대신 관리해줌)
  • MVC 패턴에서 Controller로 이용
  • HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속
  • UDP보다 처리 속도가 느림
  • HTML 변경 시 Servlet을 재컴파일해야 하는 단점

 

Servlet의 동작 방식

  1. 사용자(클라이언트)가 URL을 입력하면 HTTP Request가 Servlet Container로 전송
  2. 요청을 전송받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체를 생성
  3. web.xml을 기반으로 사용자가 요청한 URL이 어느 서블릿에 대한 요청인지 찾기
  4. 해당 서블릿에서 service메소드를 호출한 후 클리아언트의 GET, POST여부에 따라 doGet() 또는 doPost()를 호출
  5. doGet() or doPost() 메소드는 동적 페이지를 생성한 후 HttpServletResponse객체에 응답
  6. 응답이 끝나면 HttpServletRequest, HttpServletResponse 두 객체를 소멸

추가정보

WAS(Web Application Server)

더보기

동적 요청을 처리(JVM, Tomcat)

  • httpServletRequest 객체 : 정보 뭉텅이(전달받은 데이터) -> 나중에 새로운 동적 페이지를 만들 때 사용
  • httpServletResponse 객체 : 빈 객체 -> 나중에 DB와  httpServletRequest의 데이터들로 만든 결과 페이지를 담아 WEB으로 다시 돌려보냄(즉, 결과물)
  • doGet(), doPost() : Web.xml에서 해당 요청을 처리하는 survlet에 doGet(), doPost()함수를 실행
  • httpServletResponse를 WEB에 다시 보내면서 쓰레드는 사라짐
반응형

'Spring' 카테고리의 다른 글

Spring 데이터로 작업하기 1  (0) 2022.05.18
Spring 웹 애플리케이션 개발 3  (0) 2022.05.11
Spring 웹 애플리케이션 개발 2  (0) 2022.05.11
Spring 웹 애플리케이션 개발 1  (0) 2022.05.11
Spring 기초 - 1  (0) 2022.05.09

+ Recent posts