[SpringBoot]인스타그램 2강 컨트롤러
컨트롤러(Controller)란?
사용자의 요청에 맞는 Java 파일을 호출할 수 있게 분기해주는 역할을 한다. 프로그램의 가장 앞부분에서 분기하기 때문에 이를 FrontController라고 부른다. 웹 페이지에서 이루어지는 수 많은 요청을 관리하기 위해 요청의 종류별로 FrontController를 분류한다. 사용자에 관한 요청은 UserController, 게시판에 관한 요청은 BoardController 등 파일을 따로 만들어서 도메인 별로 분기되게 만든다. 스프링에서는 Dispatcher가 이 일을 한다.
HTTP 요청
서버와 클라이언트가 데이터를 교환하기 위한 요청. HTTP 요청의 종류에는 GET, POST, PUT, DELETE가 있다.
HTTP 요청 종류
종류 | 의미 | 비고 |
GET | 데이터 요청 | |
POST | 데이터 전송 | HTTP BODY 필요 |
PUT | 데이터 갱신 | HTTP BODY 필요 |
DELETE | 데이터 삭제 |
컨트롤러에서 HTTP 요청하기 예제
package com.cos.photogramstart; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; //@Controller // File을 응답하는 컨트롤러(클라이언트가 브라우저면 html 파일을) @RestController // Data를 응답하는 컨트롤러(클라이언트가 핸드폰이면 데이터를) public class HttpController { // http://localhost:8080/get @GetMapping("/get") public String get() { return "get요청됨"; } // http://localhost:8080/post @GetMapping("/post") public String post() { return "post요청됨"; } // http://localhost:8080/put @GetMapping("/put") public String put() { return "put요청됨"; } // http://localhost:8080/delete @GetMapping("/delete") public String delete() { return "delete요청됨"; } }
Path Valuable과 Query String
사용자가 데이터 요청을 구체적으로 하기 방법으로 스프링부트에서는 주로 Path Valueable방식을 사용한다.
Path Valuable 요청 방식의 주소http://localhost:8080/board/1
Query String 요청 방식의 주소http://localhost:8080?board=1
package com.cos.photogramstart; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; public class QueryPathController { @GetMapping("/chicken") public String chickenQuery(String type) { return type+"배달갑니다.(쿼리스트링)"; } @GetMapping("/chuicken/{type}") public String chickenPath(@PathVariable String type) { return type+"배달갑니다.(패스밸리어블)"; } }
HTTP HEADER & BODY
HTTP 요청시 데이터 부가적인 정보를 전송할 수 있는데 이를 HTTP 헤더라고 부르고 전송하는 데이터를 바디라고 부른다. 헤더에는 Content-Type이라는 데이터의 타입을 명시하는 부분이 존재한다. 스프링에서는 Content-Type의 디폴트 값이 x-www-form-urlencoded 타입이다.
Context-Type의 종류
Content-Type | 데이터 형태 |
x-www-form-urlencoded | key=value |
text/plain | 문자열 |
application/json | { “key” : “value” } |
1.x-www-form-urlencoded
@PostMapping("/body1")
public String xwwwformurlencoded(String username) {
log.info(username);
return "key=value 전송옴";
}
2.text/plain
@PostMapping("/body2")
public String plaintext(@RequestBody String data) {
log.info(data);
return "text/plain 전송옴";
}
3.application/json
전체 데이터
@PostMapping("/body3")
public String applicationjson(@RequestBody String data) {
log.info(data);
return "json 전송옴";
}
데이터 선택
@PostMapping("/body4")
public String applicationjsonToObject(@RequestBody User user) {
log.info(user.getUsername());
return "json 전송옴";
}
전체코드
package com.cos.animalapp.web; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.cos.animalapp.domain.User; @RestController public class HttpBodyController { private static final Logger log = LoggerFactory.getLogger(HttpBodyController.class); @PostMapping("/body1") public String xwwwformurlencoded(String username) { log.info(username); return "key=value 전송옴"; } @PostMapping("/body2") public String plaintext(@RequestBody String data) { log.info(data); return "text/plain 전송옴"; } @PostMapping("/body3") public String applicationjson(@RequestBody String data) { log.info(data); return "json 전송옴"; } @PostMapping("/body4") public String applicationjsonToObject(@RequestBody User user) { log.info(user.getUsername()); return "json 전송옴"; } }
json 응답 – 데이터 리턴
json 타입의 데이터를 응답받을 때 스프링부트가 내부적으로 가지고 있는 MessageConverter를 이용하면 직접 json으로 코드를 짜서 응답하는 불편함을 해결해 줄 수 있다. MessageConverter는 @RestController를 사용했을 때만 작동한다. @Controller를 사용할 경우 리턴타입에 @ResponseBody를 추가하면 MessageConverter를 작동 시킬 수 있다.
package com.cos.animalapp.web; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.cos.animalapp.domain.User; @RestController public class HttpResponseJsonController { @GetMapping("/resp/json") public String respJson() { return "{\"username\":\"cos\"}"; } @GetMapping("/resp/json/object") public String respJsonObject() { User user = new User(); user.setUsername("홍길동"); String data = "{\"username\":\""+user.getUsername()+"\"}"; return data; } @GetMapping("/resp/json/javaobject") public User respJsonJavaObject() { User user = new User(); user.setUsername("홍길동"); return user; // 1. MessageConverter 작동 : JavaObject를 Json(旧 xml)으로 변경해서 통신을 통해 응답을 해준다. // 2. @RestController 일때만 MessageConverter가 작동한다. } }
@Controller에서 @ResponseBody 사용법
package com.cos.animalapp.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.cos.animalapp.domain.User;
@Controller
public class HttpResponseJsonController {
@GetMapping("/resp/json/javaobject")
public @ResponseBody User respJsonJavaObject() {
User user = new User();
user.setUsername("홍길동");
return user;
}
}
결과 화면
html 응답 – 파일 리턴
자바코드가 포함되어 있는 파일을 브라우저가 해석하기 위해서는 템플릿 엔진(Template Engine)을 사용한다. 내부적으로 템플릿 엔진을 포함하고 있는 대표적인 예로 mustache와 jsp가 있다. 기본적으로 스프링에서는 mustache를 지원하지만 여전히 한국에서는 jsp를 많이 사용하기 때문에 jsp 사용법도 알아두는 것이 좋다.
txt 파일 응답
디폴트 경로 : resources/static
Controller
@GetMapping("/txt")
public String txt() {
return "a.txt";
}
a.txt
This file is a.txt.
결과 화면
mustache 파일 응답
디폴트 경로 : resources/templates
mustache 사용하기
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mustache --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mustache</artifactId> </dependency>
라이브러리 추가 후 서버 재시작
controller
@GetMapping("/mus")
public String mus() {
return "b";
}
b.mustache
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>This file is b.mustache.</h1>
</body>
</html>
jsp 파일 응답
디폴트 경로 : src/main/webapp/WEB-INF/views
jsp 사용하기
<dependencies> <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jasper</artifactId> <version>9.0.41</version> </dependency>
라이브러리 추가 후 서버 재시작. 템플릿 엔진은 하나만 사용할 수 있다.
경로 설정하기
jsp는 스프링부트에서 지원하고 있지 않기 때문에 경로를 직접 설정(viewResolver 설정)해야 한다.
spring: mvc: view: prefix: /WEB-INF/views/ suffix: .jsp
controller
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>This file is c.jsp</h1>
</body>
</html>
c.jsp
@GetMapping("/jsp")
public String jsp() {
return "c";
}
jsp 파일에서 Java 코드 사용
방법1
controller
@GetMapping("/jsp/java")
public String jspToJava() {
return "d";
}
d.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>This File is d.jsp</h1>
<%
int num = 10;
%>
<h3>num의 값은 <%=num %></h3>
</body>
</html>
결과 화면
방법2
controller
@GetMapping("/jsp/java/model")
public String jspToJavaToModel(Model model) { // 1. 함수의 파라미터에 Model을 선언한다.
User user = new User();
user.setUsername("sai");
model.addAttribute("username", user.getUsername()); // 2.addAttribute 함수로 전달한다.
return "e";
}
e.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>This file is e.jsp</h1>
<h3>${username}</h3>
</body>
</html>
결과 화면
Redirect
리다이렉트는 이미 만들어둔 코드를 재사용하기 위해 사용하는 방법으로 요청한 주소와 응답한 주소가 서로 다르다.
package com.cos.animalapp.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HttpRedirectionController {
@GetMapping("/home")
public String home() {
return "home";
}
@GetMapping("/away")
public String away() {
return "redirect:home";
}
}
리다이렉트