1. 프로젝트 환경설정
🍃 Spring initializr로 스프링 프로젝트를 생성하는 작업
🔸 빌드 자동화 도구로 gradle을 주로 사용한다.
빌드 자동화 도구란 ? 프로젝트의 빌드 과정( 컴파일-테스트-패키징-배포 ), 의존성 관리( 외부 라이브러리나 모듈을 프로젝트에 자동으로 포함 )등을 자동화한다.
빌드 스크립트를 정의하여 빌드를 실행할 때마다 수행할 작업을 설정하고 관리하는 것이다.
- maven : 아파치의 빌드자동화 도구로 XML 파일(pom.xml)로 관리한다. ( 표준화 )
- gradle : Groovy 또는 Kotlin DSL을 사용해 빌드 스크립트를 작성한다. ( 유연성, 성능 향상 )
🔸 스프링부트의 버전은 정식 릴리즈된 상태에서 가장 높은 버전을 선택한다.
snapshot은 개발중인 상태, M1은 정식배포되지 않은 상태
🔸 Project Metadata : 프로젝트 고유식별자
group은 역순 도메인으로 사용, artifact는 빌드의 결과, jar파일 이름으로 사용
🔸 Dependencies : 스프링부트로 프로젝트를 수행할때 사용할 라이브러리
- spring web - 웹개발 핵심기능 라이브러리(MVC구조를 구축, RESTful 웹서비스, HTTP응답처리..)
- thymeleaf - HTML을 만들어주는 템플릿 엔진
이후 인텔리제이에서 다운로드 받은 스프링폴더(zip)의 build.gradle을 open한다.
첫 오픈시 외부에서 라이브러리가 다운로드된다.
🍃 기본적인 구조
🔸 idea : 인텔리제이에서 관리하는 파일
🔸 gradle : gradle에서 관리하는 파일
🔸 src/main/java : 실제 실행 프로그램
🔸 src/main/resources : 자바코드파일을 제외한 설정파일, html파일 등..
🔸 gitignore : git에는 필요한 소스코드만 업로드되고 빌드된 결과물은 기본적으로 제외한다.
🔸 build.gradle : gradle의 빌드 스크립트( groovy )
- 플러그인 : Gradle에서 특정 기능을 추가하거나 확장하기 위해 사용하는 모듈
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.2'
id 'io.spring.dependency-management' version '1.1.6'
}
- 의존성 : 프로젝트가 필요한 외부 라이브러리(의존성)를 선언한다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
라이브러리 다운 경로, 공식사이트로 자동지정된다. 필요시 특정 사이트 URL을 넣을 수도 있다.
repositories {
mavenCentral()
}
- 빌드 과정에서 수행해야하는 작업을 테스크로 정의한다.
커스텀 테스크로 사용자가 직접 커스텀 태스크를 추가할 수도 있다.
테스트 작업시 JUnit Platform(주로 JUnit 5)를 사용하여 실행한다. ( 기본적으로 Gradle은 JUnit 4를 기반으로 테스트 )
tasks.named('test') {
useJUnitPlatform()
}
- 자바 버전관리
group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
- configurations 블록 : 프로젝트의 의존성(configuration)을 추가적으로 정의
- compileOnly : 컴파일 타임에만 필요한 의존성을 정의한다. ( 컴파일할 때는 필요하지만 런타임에는 필요하지 않은 의존성 ) 주로 컴파일 타임에 Java 소스 코드를 분석하고 처리하는 도구인 annotationProcessor를 정의하는데 많이 사용된다.
- extendsFrom : 특정 의존성 구성을 다른 구성으로 확장
🍃 라이브러리 살펴보기
선택한 라이브러리들이 의존하고 있는 다른 라이브러리들을 자동으로 로딩한다.
🔸 스프링부트 라이브러리들의 의존관계
- spring-boot-starter-web
- spring-boot-starter-tomcat: 톰캣(웹서버)
- spring-webmvc: 스프링 웹 MVC
- spring-boot-starter-thymeleaf : 템플릿엔진(view)
- spring-boot-starter(공통): 스프링부트 관련 라이브러리( 스프링 부트 + 스프링 코어(core) + 로깅 )
대부분의 스프링부트관련 소스에서 의존관계로 로딩된다. 이것을 통해 부트, 코어 등 기본적인 기능들이 모두 로딩된다.
웹서버(WAS)(ex. 톰캣)를 설치한뒤 자바코드를 밀어넣어서 실행하는 방식으로 진행( 웹서버와 개발라이브러리가 분리 )하지 않고 소스 라이브러리에서 웹서버를 내장하여(embedded) 실행시 웹서버를 띄울 수 있다.
🍃 View 환경설정
🔸 스프링 부트가 제공하는 Welcome Page 기능
도메인 접속시의 첫화면, index.html 파일이 시작페이지로 설정된다. ( main/resources/static/index.html )
🔸 템플릿 엔진
Spring Boot includes auto-configuration support for the following templating engines : FreeMarker, Groovy, Thymeleaf, Mustache
타임리프 : 상단에 타임리프(th)를 선언해두면 템플릿엔진으로 타임리프 문법을 사용할 수 있다.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
...
<head>...</head>
<body>...</body>
</html>
🔸view의 처리과정
웹서버 : 클라이언트(웹 브라우저)로부터 요청을 받아서 그에 대한 응답을 제공한다. ( Apache HTTP Server, Nginx, Microsoft IIS .. )
- Apache Tomcat : 웹서버의 역할( HTTP 요청에 따른 정적 컨텐츠(HTML, CSS, 이미지 ...) 제공 ) & 서블릿 컨테이너 역할( Java서블릿과 JSP(JavaServer Pages)를 실행 )
스프링부트에 라이브러리로 내장되어 있다.(embedded)
Spring 애플리케이션 : 웹 서버에서 실행될 수 있는 애플리케이션의 동작을 프로그래밍한 것 ( 웹서버에서 동작하는 애플리케이션 )
- controller에서 요청과 매핑되는 메서드가 실행된다.
- view Resolver가 return문값과 일치하는 view페이지를 찾아서 반환한다.( resources:templates/ +{ViewName}+ .html 로 매핑 ) ( 먼저 template하의 페이지-> 이후 static하의 페이지 )
- 템플릿 엔진이 이를 동적으로 랜더링한다. 이때 스프링이 model을 만들어 데이터를 매개변수로 전달한 것을 사용할 수 있다.
🔸 콘솔에서 빌드작업( 배포작업 )
프로젝트 폴더하에 gradlew파일이 있는 것을 확인하고 build 작업 수행( gradlew build )
이후 build/libs 하에 jar파일이 완성되어있다. ( 서버 배포시에 이용되는 서버프로그램 )
java -jar 명령을 통해 해당 jar파일을 실행하면 스프링이 실행된다.
다시 빌드하는 경우 gradlew clean으로 build폴더 자체를 삭제시키고 다시 진행할 수 있다.
2. 스프링 웹개발 기초
웹개발에는 3가지 방법이 존재한다.
- 정적 컨텐츠 : 서버의 처리없이 파일(정적 페이지)을 웹브라우저에 전달한다.
- MVC와 템플릿 엔진 : 서버에서 프로그래밍처리를 거친 동적인 페이지를 템플릿 엔진이 생성하여 전달한다.
템플릿 엔진은 서버 측에서 주어진 데이터와 템플릿(HTML 템플릿 파일)을 결합하여 최종 HTML 페이지를 생성 - API : 데이터구조 포맷(ex. json, XML )으로 브라우저에 데이터를 전달한다.
데이터만 전달하면 클라이언트에서 화면을 구성하는 방식, 서버끼리 통신하는 방식에서 사용
🍃 정적 컨텐츠
스프링부트에서 기본적으로 정적컨텐츠기능을 제공한다.
Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath
웹브라우저가 요청을 내장 톰캣 서버에서 받게된다.
- controller(src/main/java)에서 해당 요청을 처리하는 매핑이 있는지 탐색한다. ( controller가 우선순위를 가짐 )
- 없다면 내부의 정적 컨텐츠 위치(src/main/resources/static)에서 해당 페이지를 찾아 반환한다.
🍃 MVC와 템플릿 엔진
- Model1방식 : JSP를 통해 뷰와 컨트롤러 처리를 한꺼번에 수행한다. 뷰에서 요청처리를 모두 수행한다.
- MVC방식 : Model, View(화면구성), Controller(비즈니스 로직, 내부처리)로 관심사를 분리하여 개별 수행한다.
- 내장 톰캣 서버 : HTTP 요청을 수신
- Controller : 적절한 Controller로 매핑(DispatcherServlet이 HandlerMapping을 사용), 컨트롤러의 요청처리후 모델데이터(model)와 논리적 뷰이름을 반환(return)
- View Resolver : 논리적 뷰이름을 이용해 실제경로 결, 템플릿 엔진이 랜더링하여 최종 HTML 응답을 생성
이때 정적 컨텐츠는 DispatcherServlet이 아닌 톰캣 서버나 Spring Boot의 정적 리소스 처리 기능에 의해 직접 제공된다. 따라서 뷰 리졸버의 역할에서 벗어나게 된다. 뷰 리졸버는 주로 동적 페이지를 찾고 처리할 때 동작한다.
🔸 Controller 코드
@Controller
public class HelloController {
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
}
- Model : view에서 랜더링 작업할때 해당 데이터를 사용할 수 있다.
- @RequiredParam의 required속성은 기본이 true이기에 매개변수를 전달하지 않으면 동작하지 않는다. ( MissingServletRequestParameterException )
🔸 View코드( resources/templates/hello-template.html )
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
- 타임리프의 장점은 HTML파일을 작성후 서버없이 오픈가능하다는 것! ( absolute path로 파일에 접근하면 데이터가 없는 상태로 접근가능 )
서블릿(Servlet)
- 서블릿 정의 : HTTP 요청을 처리하는 자바 웹 컴포넌트이다.
- 클래스 구성 : 서블릿 클래스는 HttpServlet 클래스를 상속받아야 하며, doGet(), doPost() 등의 메서드를 오버라이드하여 요청을 처리한다. 요청 처리 결과를 HttpServletResponse 객체를 통해 클라이언트에 응답으로 반환한다.
- 배포위치 : 웹 애플리케이션의 WEB-INF/classes 디렉토리에 배포되며, 서블릿 컨테이너가 이 클래스를 로드하고 실행한다.
이러한 서블릿을 포함한 웹 애플리케이션이 일반적이며 이는 서블릿 컨테이너(Tomcat, Jetty 등) 에 배포되어야한다. 이러한 애플리케이션은 동적 콘텐츠와 정적 콘텐츠(HTML, CSS, JS, 이미지 등) 모두를 처리할 수 있다. 서블릿을 포함하지 않는 웹 애플리케이션은 정적 콘텐츠(HTML, CSS, JS, 이미지 등)만 제공할 수 있으며 기본적인 순수 웹서버(Nginx, Apache HTTP Server)에 배포될 수 있다.
서블릿이 있는 웹 서버 애플리케이션에서는 모든 요청(정적 및 동적)이 일단 서블릿 컨테이너로 전달되어 처리된다. 동적요청은 사용자정의 서블릿이나 JSP에 의해 처리되고 정적요청은 서블릿 컨테이너가 포함하는 기본 서블릿(DefaultServlet)에 의해 처리된다.
그러나 정적 요청의 처리에서는 순수웹서버가 더욱 효율적이기에 서블릿 컨테이너 앞에 순수 웹 서버 (Nginx, Apache HTTP Server 등) 를 프록시로 설정하여 정적 자원을 처리하게 함으로써 성능 최적화를 할 수 있다.
스프링 프레임워크와 같은 현대적인 프레임워크에서는 서블릿을 직접 사용하는 대신, 서블릿을 기반으로 하는 컨트롤러를 사용합니다.
Spring framework에서는 특수서블릿 DispatcherServlet을 제공한다.
- 중앙처리기 : 스프링 애플리케이션의 모든 HTTP 요청을 받아들인다.
- 요청분배 : 요청 URL, HTTP 메서드 등을 기준으로 적절한 컨트롤러로 라우팅한다. 이 과정에서 ( HandlerMapping 이용 )
- 뷰 결합 : 컨트롤러의 요청처리로 반환된 모델 데이터를 적절한 뷰와 결합하여 응답을 생성한다. ( ViewResolver 이용 )
Spring에서 웹 애플리케이션을 개발할 때 컨트롤러를 작성하면, DispatcherServlet이 자동으로 설정되어 이를 처리한다. 개발자는 DispatcherServlet을 직접 만들거나 설정할 필요가 없으며, Spring이 이를 자동으로 구성해준다. 이로써 비즈니스 로직개발에만 집중할 수 있다는 장점이 있다!!
즉 Spring Framework의 가장큰 장점은 자동 구성되는 서블릿(DispatcherServlet)기반의 MVC 패턴(관심사의 분리)을 활용하여 복잡한 요청 처리와 응답 생성을 더 쉽게 관리할 수 있게 해준다는 것이다.
서블릿 컨테이너( Servlet container )
: 서블릿이 실행되는 환경으로 이를 통해 서블릿의 생명 주기를 관리하고, 요청과 응답을 처리하며, 세션을 관리하는 등의 작업을 수행한다.
- 생명 주기 관리 : 각 서블릿의 init(), service(), destroy() 메서드를 호출하며 서블릿의 생성, 초기화, 요청 처리, 종료 등의 생명 주기를 관리한다.
- 요청/응답 처리 : 클라이언트의 HTTP 요청( javax.servlet.http.HttpServletRequest )을 서블릿에 전달하고, 서블릿에서 생성된 응답( javax.servlet.http. HttpServletResponse )을 클라이언트에게 전달한다.
Spring MVC에서는 HttpServletRequest를 직접 사용하거나, @RequestParam, @PathVariable, @RequestBody 등을 통해 요청 파라미터를 주입받을 수 있다. - 세션 관리: 사용자 세션을 관리하고, 세션에 저장된 데이터를 서블릿에서 사용할 수 있도록 제공한다.
HttpServletRequest 객체를 통해 세션(HttpSession)을 생성하고 관리한다. 세션데이터를 읽거나 저장할 수 있다. - 서블릿 매핑 : 특정 URL 패턴을 서블릿(또는 컨트롤러)과 연결하여, 해당 URL로 들어오는 요청이 적절한 서블릿에 전달되도록 설정합니다. 이는 web.xml 파일 또는 애너테이션 기반의 설정을 통해 이루어진다.
- JSP 처리 : HTML과 Java 코드가 혼합된 웹 페이지를 생성하는 JSP(JavaServer Pages)는 서블릿 컨테이너에 의해 서블릿으로 변환됩니다. JSP 파일은 서블릿으로 컴파일된 후, 서블릿 컨테이너에서 실행되어 최종 HTML 응답을 생성합니다.
🍃 API
- 내장 톰캣 서버 : HTTP 요청을 수신
- Controller : 적절한 Controller로 매핑(DispatcherServlet이 HandlerMapping을 사용), 데이터값을 반환한다.
- HttpMessageConverter : 데이터값을 HTTP 응답본문으로 변환하는 역할을 수행하는 것으로 @ResponseBody어노테이션에 의해 호출된다. ( * 직렬화 = serialize: 자바객체를 응답본문으로 변환하는 것 )
여러 HttpMessageConverter가 기본으로 등록되어 있고 컨트롤러의 반환타입과 HTTP accept헤더( 응답시 원하는 데이터포맷을 지정 )에 따라 적절한 converter가 동작하여 반환되는 데이터타입을 응답본문으로 변환시킨다.
( StringHttpMessageConverter(string), MappingJackson2HttpMessageConverter (object-> json), Jaxb2RootElementHttpMessageConverter(XML), ByteArrayHttpMessageConverter(byte) 등... )
🔸 Controller 코드
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name){
return "hello "+name;
}
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name){
Hello hello = new Hello();
hello.setName(name);
return hello;
}
static class Hello{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Responsebody : HTTP통신의 응답 body부분에 직접 데이터를 넣어주겠다는 의미의 어노테이션
뷰를 반환하지 않는다. 뷰리졸버 및 템플릿엔진이 동작하지 않게 된다.
단순문자라면 StringConverter(StringHttpMessageConverter)가 동작하여 자바 문자열을 HTTP응답본문으로 변환하고
객체라면 JsonConverter(MappingJackson2HttpMessageConverter)가 동작하여 자바 객체를 json형태(객체타입에 대해 기본으로 설정된 직렬화 형태)로 만들어 반환한다. JSON (JavaScript Object Notation) : { key : value }로 이루어 데이터 교환 포맷
( 객체->json 변환 라이브러리(Jackson, Gson)중 Jackson을 기본으로 함 )
'web programming' 카테고리의 다른 글
[ 스프링 입문 ] 스프링 빈과 의존관계 (0) | 2024.09.02 |
---|---|
[ 스프링 입문 ] 회원관리 예제 (1) | 2024.09.02 |
JPA(Java Persistence API) 기본개념 (0) | 2024.03.10 |
SpringBoot 기본개념 (0) | 2024.03.10 |
JQuery를 이용한 웹프론트 페이지 클론코딩 (0) | 2024.03.10 |