스프링 부트 (Spring Boot) 로 시작하는 프레임워크 (Framework)

🗓 ⏰ 소요시간 21 분

스프링을 사용하다보니 좋은 프레임워크긴 하지만 지옥같은 XML 설정과 방대한 양의 코드 때문에 애를 먹었습니다. 간단한 소규모 혹은 개인 프로젝트에서도 스프링을 사용하고 싶은데 왠지 무거운 느낌입니다. 그러던 중 예전에 들었던 스프링부트가 생각나서 프로토타입을 만들 때 적용해보기로 했습니다. 많은 설정을 자동화시켜서 훨씬 쉽고 간단하게 사용할 수 있다고 합니다. 그렇다면 스프링 프레임워크를 시작하기 전에, 먼저 프레임워크가 무엇인지부터 알아보겠습니다.

프레임워크 (Framework)

디자인 패턴 (Design Pattern)

절차형 언어에서 객체지향 언어로 넘어오면서 설계의 중요성이 커졌습니다. 객체지향은 객체들이 서로 메시지를 주고 받고 서로를 사용하면서 작업을 수행하기 때문에 객체를 어떻게 설정하고 객체 간 관계를 어떻게 정할 것인지, 이런 설계 작업이 핵심적으로 중요해졌습니다.

객체지향을 처음 배우는 사람들에게 이런 설계 개념을 설명하기 위해서 기존 개발 건 중에 설계가 잘 된 케이스들을 뽑아서 가르치기 시작했습니다. 이런 케이스들을 이름을 붙이고 목적과 용도, 그리고 구현 방법을 잘 정리해놓은 것이 바로 디자인 패턴 입니다. 그래서 아무렇게나 설계하는 것이 아니라 필요한 디자인 패턴을 참고해서 설계하면 효율적으로 설계할 수가 있게 되었죠.

라이브러리 (Library)

라이브러리는 어떠한 기능을 다른 사람들도 사용할 수 있도록 만들어 놓은 것을 말합니다. 예를 들어, 내가 만드는 애플리케이션 안에 이미지 변환 기능이 필요하다고 합시다. 그러면 이미지 변환 기능이 필요한 사람들은 모두 기능을 각자 구현해야곘죠. 하지만 그렇게 하지 않고 이미지 변환 기능을 다른 사람들도 소스 안에서 사용할 수 있도록 jar 형태로 묶어서 제공하는 것이 바로 라이브러리입니다.

프레임워크 = 디자인 패턴 + 라이브러리

프레임워크란 이름에서부터 알 수 있듯이 애플리케이션을 개발할 때 사용하는 일종의 을 말합니다. 앞서 말한 디자인패턴과 라이브러리들을 모아서 프로그램 형태로 만들어놓은 겁니다. 그래서 프레임워크를 사용하면 여러가지 유용한 기능을 통해 개발자는 구현해야 하는 핵심 로직에 집중할 수가 있습니다.

예를 들어, 나는 해변에 앉아 있는 사람을 그리고 싶다면, 이미 해변 그려져 있는 해변 그림을 가져다가 내가 그리고 싶은 앉아 있는 사람만 그리는 거라고나 할까요.

이를 통해서 사용자는 개발 생산성 향상과 일정 수준 이상의 품질을 보장받을 수 있습니다. 개발자의 실력에 상관없이 고급 기능들을 적용할 수 있기 때문에 대규모 프로젝트에서는 프레임워크를 반드시 사용합니다.

스프링 프레임워크 (Spring Framework)

스프링 프레임워크 는 자바 기반의 애플리케이션 프레임워크입니다. 웹 애플리케이션 서버 사이드 개발 시 많이 사용되고, 웹 뿐만 아니라 많은 곳에서 사용된다고 합니다. 스프링 홈페이지에 가보면 상당히 많은 프로젝트 가 있습니다. 우리나라 공공기관 웹 서비스 개발할 때 사용하는 전자정부 프레임워크도 스프링 기반으로 되어있습니다.

스프링 핵심 기능

스프링의 핵심 기능은 다음과 같습니다. 각각에 대해서 설명하기에는 양이 너무 방대하니 자세한 내용은 다른 포스팅을 통해서 하나씩 알아보기로 하죠.

  • 의존 주입 (Dependency Injection)
  • 관점 지향 프로그래밍 (AOP; Aspect-Oriented Programming)
  • 스프링 MVC 웹 애플리케이션과 RESTful 웹 서비스 프레임워크 (Spring MVC web application and RESTful web service framework)
  • JDBC, JPA, JMS 지원

스프링 모듈

https://docs.spring.io/spring/docs/current/spring-framework-reference/

스프링은 여러가지 모듈로 이뤄져 있어서 내가 필요한 모듈만 뽑아서 사용할 수가 있습니다. 정말 유용한 기능이 많지만 방대하고 내용이 많아서 공부해야할 난이도도 올라갑니다.

스프링 부트 (Spring Boot)

http://projects.spring.io/spring-boot/

스프링 부트는 스프링의 여러가지 프로젝트 중 하나입니다. 스프링을 사용해보신 분들은 아시겠지만 설정할 내용도 굉장히 많고, XML 파일로 설정할 경우 정말 눈이 빠질만큼 힘듭니다. XML 은 컴파일도 안되니 오타 하나만 나도 찾기가 정말 어렵죠.

이런 단점들을 보완해서 간단히 실행할 수 있는 것이 스프링 부트입니다. 시작해보시면 알겠지만 설정할 것도 거의 없고 그냥 실행 만 시키면 내장 서버에 배포되어 바로 뜹니다. 기존에 설정하던 것들을 자동화시켜서 많이 걷어냈습니다. 그래서 프로토타입을 만들 때 스프링 부트를 활용해보기로 결정했습니다.

기능

  • 내장 서버: WAR 파일을 배포할 필요 없이 내장된 Tomcat, Jetty, Unertow 를 이용해 실행할 수 있습니다.
  • 간단한 라이브러리 관리: 많이 사용하는 라이브러리를 모아놓은 스타터 (Starter) POM 파일로 메이븐 설정이 쉬워집니다.
  • 자동 설정: 더 이상 XML 설정이 필요하지 않습니다.
  • 레퍼런스 가이드 (Reference Guide): 문서화가 잘 되어 있어서 개발할 때 찾아보기 편합니다.

스프링 부트 시작하기

Spring Tool Suite

스프링 부트를 시작하기 위해 Spring Tool Suite (이하 STS) 를 설치합니다. STS는 이클립스 (Eclipase) 기반의 스프링 개발 환경입니다.

설치는 STS 홈페이지에서 압축 파일을 다운로드 받아 원하는 곳에 압축을 해제하면 됩니다. 혹은 기존에 사용하는 이클립스에서 스프링 플러그인을 설치해서 사용할 수도 있습니다.

Hello, Spring Boot!

역시 새로 배울 때는 ‘Hello, world’ 죠. 사용자의 이름을 받아서 Hello, World랑 같이 화면에 뿌려보겠습니다.

프로젝트 생성

new > Spring Starter Project 로 프로젝트를 생성합니다. 프로젝트 이름을 입력하고 메이븐 (Maven) 을 이용해서 진행하겠습니다.

프로젝트를 생성할 때 미리 POM 파일을 구성할 수 있습니다. 어지간한 건 거의 다 있어서 클릭만하면 되니까 편하군요. 물론 이후에도 POM 파일을 수정 가능합니다. 아래 세 가지 모듈을 선택하고 완료를 누르면 필요한 라이브러리들을 모두 다운받습니다.

  • Web : 웹 개발 관련 라이브러리 모음
  • Velocity : 템플릿 엔진 중 하나인 Velocity
  • DevTools : 개발 툴로 서버 자동 재시작 등을 지원

프로젝트 생성 완료 후 패키지 구조입니다.

1
2
3
4
5
6
7
8
9
10
11
12
HelloSpring [boot][devtools]
├─ src/main/java
├─ com.han
├─ HelloSpringApplication.java
├─ ServletInitializer.java
├─ src/main/resources
├─ static
├─ templates
application.properties
├─ src/test/java
├─ target
pom.xml

인덱스 (Index) 페이지 만들기

src/main/resources/static 경로에 index.html 을 추가합니다. index.html 은 기본 URL 로 접속 시 접속되는 화면입니다. static 폴더는 사이트의 정적인 파일들을 관리할 때 사용합니다. 정적 HTML 문서, 이미지, 영상 등이 있습니다.

index.html
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body>
<h1>INDEX</h1>
</body>
</html>

컨트롤러 (Controller) 만들기

com.han.web 패키지를 만들어서 HelloController.java 를 생성합니다.

HelloController.java
1
2
3
4
5
6
7
8
@Controller
public class HelloController {

@RequestMapping("/hello")
public @ResponseBody String hello() {
return "Hello, Spring Boot!";
}
}

컨트롤러는 Dispatcher Servlet 에서 받은 요청에 따라 로직을 처리하는 역할을 합니다. 여기서는 /hello라는 경로로 오는 요청에 "Hello, Spring Boot!"라는 응답을 보냅니다. @ResponseBody 어노테이션을 이용해 String 자체를 응답의 body로 사용해서 보냅니다.

실행하기

이제 실행을 해봅니다. 따로 서버 구성할 필요 없이 HelloSpringApplication.java 파일을 오른쪽 클릭해서 Run as.. > Spring Boot App 으로 실행합니다.

HelloSpringApplication.java
1
2
3
4
5
6
7
8
@SpringBootApplication

public class HelloSpringApplication {

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

웹 애플리케이션인데 메인 함수가 있군요. 내장된 톰캣 대신 설정을 통해 JettyUndertow를 사용할 수도 있고, 외부 서버를 사용할 수도 있습니다.

기본 포트는 8080 입니다. 포트 충돌 에러가 나시는 분들은 src/main/resources/application.properties 에서 다음과 같이 작성하고 8080 대신 다른 포트로 수정합시다.

1
server.port = 8080;

잘 떴다면 이런 로그가 뜹니다.

1
2
Tomcat started on port(s): 8080 (http)
Started HelloSpringApplication in 2.047 seconds (JVM running for 2.794)

http://localhost:8080/로 접속해보면 index.html 화면을 볼 수 있고, http://localhost:8099/hello로 접속하면 ‘Hello, Spring Boot!’ 를 확인할 수 있습니다.

Hello, Eric!

이번에는 이름을 같이 출력하도록 변경해보겠습니다. 다음과 같은 순서로 동작하게 됩니다.

  1. 클라이언트에서 /hello 경로로 서버에 name 을 전달합니다. (GET 방식)
  2. 서버는 문자열을 조립해서 greetings 라는 스트링을 만들고 클라이언트에 응답합니다.
  3. 서버에서 오는 데이터를 클라이언트에서 렌더링하기 위한 템플릿 엔진으로는 Velocity 를 사용하겠습니다.
  4. Velocity 파일에서는 서버에서 받은 greetings 라는 스트링을 출력합니다.

Velocity 파일 생성하기

HTML 파일을 생성하고 다음과 같이 작성한 후에 .vm 확장자로 변경합니다.

hello.vm
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>

$greetings

</body>
</html>

$greetings 이라는 부분은 서버에서 greetings 라는 이름으로 오는 데이터를 맵핑해주는 부분입니다.

컨트롤러 수정하기

이제 컨트롤러를 해당 파라미터를 처리할 수 있도록 변경합니다.

HelloController.java
1
2
3
4
5
6
7
8
9
10
11
@Controller
public class HelloController {

@RequestMapping("/hello")
public String hello(Model model, @RequestParam(value = "name", defaultValue = "Unknown", required = false) String name) {

String greetings = "Hello, " + name + "!";
model.addAttribute("greetings", greetings);
return "hello";
}
}

@RequestParam 어노테이션을 이용해 클라이언트에서 넘어온 name 이라는 파라미터를 받습니다. @RequestParam 은 HttpRequest 로 넘어오는 파라미터와 선언한 변수를 맵핑해주는 역할을 합니다. 만약 name 을 전달하지 않는다면 에러가 납니다.

1
@RuquestParam(value="name", required=false) String name

이런 식으로 필수여부를 false 로 지정하지 않는다면 말이죠. 이럴 때는 빈 값으로 표시됩니다. 우리는 name 이 넘어오지 않는 경우에는 기본값으로 ‘Unknown’ 이라는 문자열이 나오도록 했습니다.

실행하기

아까 띄워놓은 서버는 변경이 있을 때 자동 재시작이 되므로 변경사항은 바로 적용됩니다. 이제 접속을 해봅시다.

1
http://localhost:8080/hello

Hello, Unknown!

name 이 없기 때문에 기본값으로 설정해놓은 Unknown 을 사용해 출력됩니다. 클라이언트에서 GET 방식으로 서버에 요청할 떄는 URL 뒤에 파라미터를 이어 붙여서 요청합니다. name 이라는 이름의 파라미터를 줘보겠습니다.

1
http://localhost:8080/hello?name=Eric

URL 뒤에 물음표 (?) 를 붙이고 파라미터를 적습니다. 그러면 Eric 이라는 문자열이 name 이라는 이름을 가지고 서버로 보내집니다.

Hello, Eric!

스프링부트를 이용해 아주 간단한 애플리케이션을 만들어봤습니다. 다음 포스트에서는 DB 를 설치하고 JPA 를 이용해서 스프링부트와 연결해보겠습니다.