이번 시간부터는 지금까지 배운 Spring Framework, Spring Boot, Hibernate를 이용해 Java 웹 애플리케이션을 만들어볼 것이다.
이 과정에서 복습은 당연히 이루어질 것이고, 과정 중에 겪는 어려움을 해결하기 위해 새로운 것들을 배워보기도 할 것이다.
일단 시작해보자.
언제나 그랬듯이 Spring initializr로 프로젝트를 만들어보자.
언제나처럼 빌드툴은 Maven을 선택하자. Spring Boot는 릴리즈된 버전 중 최신 버전을 사용하자.
Project: Maven
Language: Java
Spring Boot: 3.3.2
Group: com.in28minutes.springboot
Artifact: myfirstwebapp
Name: myfirstwebapp
Description: Demo project for Spring Boot
Package name: com.in28minutes.springboot.myfirstwebapp
Packageing: Jar
Java: 17
Dependencies: Spring Web, Spring Boot DevTools
Generate해서 압축 파일을 다운로드 받고, 압축을 해제한 뒤, 사용하는 IDE에서 열어주자.
일단 간단하게 Hello Wolrd라는 응답을 제공하는 애플리케이션을 만들어보자.
이를 위해 SayHelloController라는 이름의 클래스를 만들어주자.
패키지 경로는 `com.in28minutes.springboot.myfirstwebapp.hello.SayHelloController`가 될 것이다.
이후에 우리가 만들 모든 패키지는 myfirstwebapp 아래에 위치하는 서브 패키지라는 것을 기억하자.
이제 SayHelloController에 `say-hello`라는 url을 입력했을 때 `Hello World`라는 응답을 반환하도록 해보자.
```
@Service
public class SayHelloController {
@RequestMapping("say-hello")
public class sayHello() {
}
}
```
그리고 `MyfirstwebappApplication.java`를 실행한 뒤, `localhost:8080/say-hello`라고 입력하면 에러가 발생한다.
여튼 에러가 발생하는데, 이유는 Spring MVC는(@RequestMapping은 Spring MVC에서 제공하는 어노테이션이다.) 문자열을 리턴할 때 문자열을 그대로 리턴하지 않고 뷰를 검색하기 때문이다. 때문에 문자열을 그대로 반환하기 위해서는 `@ResponseBody`어노테이션을 사용해야 한다.
```
@Service
public class SayHelloController {
@RequestMapping("say-hello")
@ResponseBody
public class sayHello() {
return "Hello World";
}
}
```
이렇게 하면 문자열이 반환되는 것을 확인할 수 있다.
그런데 이렇게 문자열을 일일이 반환하는 것은 매우 번거롭다. 때문에 실제로는 HTML이라는 걸 사용한다. HTML을 어떻게 사용하는지, 어떻게 반환하는지 알아보자.
이번에는 `Hello World`라고 적혀 있는 html을 반환하는 메소드를 만들어 보자.
```
@RequestMapping("say-hello-html")
public class sayHelloHtml() {
StringBuffer sb = new StringBuffer();
sb.append("<html>");
sb.append("<head>");
sb.append("<title>My first HTML Page</title>");
sb.append("</head>");
sb.append("<body>");
sb.append("My first html page with body");
sb.append("</body>");
sb.append("</html>");
}
```
이렇게 하고 url을 입력하면 위에서 코딩한 페이지를 볼 수 있다.
그런데 이상하다. 아까 쉽게 쉽게 가려고 html을 사용한다고 했는데, 더 번거롭지 않은가...?
이유는 원래 이렇게 쓰는 게 아니기 때문이다.... 아까 Spring MVC는 뷰를 반환한다고 했는데, 이를 이용해서 html 파일을 만들어 놓고, 그 파일을 그냥 반환하면 된다.
뷰는 그냥 단순하게 사용자가 보는 화면이다. 즉, 사용자에게 정보를 어떻게 보여줄지를 결정하는 역할을 한다. 가장 널리 사용되는 뷰, 그리고 우리가 앞으로 사용할 뷰는 JSP, Java Server Pages라고 부르는 뷰가 있는데, 이는 웹페이지를 만들기 위한 도구로, HTML안에 자바를 섞어 사용할 수 있게끔 해준다.
아직 자바를 섞어 사용하진 않을 것이다. 일단 메소드에서 반환할 html 파일을 만들어보자. 이름은 `sayHello.jsp`라 하자. 경로는 `src/main/resources/META-INF/resources/WEB-INF/jsp/sayHello.jsp`에 있어야 한다.
```
<html>
<head>
<title> My first HTML Page</title>
</head>
<body>
My first html page with body
</body>
</html>
```
그리고 이를 반환할 메소드는 아래와 같다.
```
@ResponseMapping("say-hello-jsp")
public String sayHelloJsp() {
return "sayHello";
}
```
return문을 보면 ...sayHello.jsp가 아니라, sayHello라고 적어놓았다. 이는 application.properties에 적어놓은 설정 덕분에 가능한 것이다.
```
prefix=/WEB-INF/jsp/
suffix=.jsp
```
`/src/main/resources/META-INF/resources`는 자동으로 삽입되므로 생략한다.
이렇게 다 하고 실행하면 오류가 날텐데, 이는 추가하지 않은 의존성이 있기 때문이다. 아래 의존성을 추가하자. 인텔리제이에서는 `<scope>provided</scope>`를 넣지 않아도 된다.
만약 이외의 다른 경우에 html 페이지에서 오류가 날 경우 inspect에 들어가서 반환하는 HTTP 상태 코드를 보고 무슨 오류인지 추측할 수 있다. 아니면 application.properties에서 로깅 수준을 debug로 바꾸어 하나하나 살펴보며 오류의 원인을 찾아볼 수도 있다. 로깅 수준을 바꾸기 위해서는 `logging.level.org.springframework=info`와 같은 코드를 추가하면 된다. 수준은 `trace`, `debug`, `info`, `warning`, `error`, `off`가 있다.
만약 패키지별로 로깅수준을 설정하고 싶다면 `logging.level.com.in28minutes.springboot.myfirstwebapp=debug`와 같이 설정할 수 있다.
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
```
아까 HTTP 이야기한 김에 말하는 건데, 우리가 만들 웹은 대충 이러한 구조로 작동한다. 브라우저가 우리가 만든 애플리케이션에 요청을 보내면 애플리케이션이 브라우저에 응답한다.
어쨌든 이렇게 하면 url을 입력했을 때 우리가 아까 하드코딩한 html 페이지를 볼 수 있다.
이번엔 login.jsp 페이지를 만들어서 sayHello.jsp에 진입하기 위한 문턱을 만들어보자.
일단 그 전에 LoginController를 만들어서 url을 입력하면 login.jsp로 진입할 수 있도록 하자.
경로는 `com.in28minutes.springboot.myfirstwebapp.login.LoginController`이 될 것이다.
```
@Controller
public class LoginController {
@RequestMapping("login")
public String gotoLoginPage() {
return "login";
}
}
```
그리고 login.jsp를 작성해보자. login form은 만들지 않고 일단 sayHello.jsp복붙해서 바꾸는 정도만하자
```
<html>
<head>
<title>Login Page</title>
</head>
<body>
Welcome to the login page~!
</body>
</html>
```
이제 여기서 입력을 처리하는 논리를 작성해볼텐데, 그 전에 입력을 받을 때 어떻게 받느냐 알아보자.
간단한 예를 통해 알아보자. 만약 name이라는 란에 tempName을 입력받으려고 한다면 url을 통해 `localhost:8080/login?name=tempName`이라 입력받을 수 있을 것이다.
물론 나중에는 폼으로 입력받을 것이고, 정보유출을 막기 위해 url에 저런 게 안 뜨도록 할 것이다. 지금은 처음 배우는 단계니까 이렇게 하는 것이다.
그리고 이를 입력받았을 때 함수로 넘기기 위해서는 함수의 매개변수에 @RequestParam 어노테이션을 붙여주면 된다.
```
@Controller
public class LoginController {
private Logger logger = LoggerFactory.getLogger(getClass()); //slf4j
@RequestMapping("login")
public String gotoLoginPage(@RequestParam String name) {
// System.out.println("Request param is " + name); // NOT RECOMMENDED FOR PROD CODE
logger.debug("Request param is {}", name);
logger.info("I want this printed at info level");
logger.warn("I want this printed at warn level");
return "login";
}
}
```
하여 name이 제대로 입력되어 출력되는 걸 확인할 수 있다. logger라는 걸 활용하였는데, 아무래도 콘솔에 출력하는 건 성능저하의 우려가 있기도 하고, 로그를 통해 출력하는 게 더 관리하기 편해서 이렇게 한 것이다. 그런데 우리가 이렇게 입력받는 건 함수 안에서만 쓰고 끝낼 것이 아니라 jsp로 넘기기 위해서 하는 것이 아닌가? 이건 어떻게 하느냐... 하면 이것도 Spring MVC에서 제공하는 기능을 이용하여 할 수 있다. ModelMap이라는 기능이 있는데 ModelMap 변수를 선언한 뒤, 변수에 값을 넘기면 jsp 파일에서도 이용할 수 있다.
```
@Controller
public class LoginController {
@RequestMapping("login")
public String gotoLoginPage(@RequestParam String name, ModelMap model) {
model.put("name", name); // key-value
return "login";
}
}
```
이렇게 넘긴 값을 jsp에서는 값을 어떻게 사용하는가 하면, 매우 간단하다. Express Language라는 걸 활용하는데, 그냥 `${variable}`같이 달러 기호를 작성한 후, 중괄호 쌍 안에 변수 이름을 넣으면 된다.
'강의 > Java Spring Boot' 카테고리의 다른 글
로그인 양식 만들기 (0) | 2025.01.26 |
---|---|
Spring MVC 작동원리 (0) | 2025.01.26 |
Spring Boot 시작하기 (1) | 2025.01.26 |
Spring과 Spring Boot로 JPA와 Hibernate 시작하기 (0) | 2024.07.30 |
CDI, XML 겉핣기 (0) | 2024.07.29 |