Spring Web MVC 구조
MVC 아키텍처 흐름이다.
여기서 Servelet이 Front Controller를 담당한다.
요청에 따라 해당 Controller로 매핑이 된다.
응답으로 보여줄 View를 처리한다.
- Controller는 손님을 맞이한다고 생각하면 된다. (배웅까지는 덤)
- Model은 db에서 데이터를 뽑아오거나 집어넣는다.
- View는 사용자 눈에 보이는 것
이라고 생각하면 쉽다.
- @Controller // @RestController
- 사용 위치: 클래스
- Controller : html을 사용시 컨트롤러를 사용
- RestController: Json사용시 RestController 사용
- html파일을 사용하지 않아서 있는 그대로 리턴값을 페이지에 출력해준다.
- API서버를 만들 때 유용
@Controller
package com.example.basic.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HtmlController {
@GetMapping("html/string")
public String htmlString() {
return "html/string";
}
}
그럼 html패키지 안에 string.html을 찾아 웹 브라우저에 string.html값을 출력해준다.
@RestController
package com.example.basic.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Json2Controller {
@GetMapping("json2/map")
public Map<String, Object> jsonMap(Map<String, Object> map) {
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("key1", "value");
map2.put("key2", 2324);
map2.put("key3", true);
return map2;
}
}
json2/map을 Get요청시
이렇게 JSON형식으로 나오게 되는 것을 볼 수 있다.
@Post // @Get
특정 HTTP 메소드 Post와 Get만을 처리하기 위해 딱 꼬집어서 사용하는 전용 어노테이션이다.
@GetMapping
HTTP 뒤에 ?가 붙어서 나오는 요청이에 대한 반환 이라고 보면 쉽다.
@GetMapping("req/get2")
public String get2(String name, int id){
return String.format("나이 %s 아이디 %s",name, id );
}
@RestController 밑에 있는 get2를 GetMapping하는 메서드이다.
http://localhost:8080/req/get2?name=jang&id=1234
name을 jang으로 하고 id를 1234로 하면 어떻게 html에 나올까?
예상했겠지만
이렇게 웹 브라우저에 출력이 되는 것을 볼 수 있다.
그래서 데이터가 URL에 노출되기 때문에 민감한 데이터를 보내는데는 적합하지 않다.
주로 서버로부터 데이터를 조회(읽어올 때) 사용된다.
@PostMapping
Get과 다르게 URL에 데이터를 붙여서 보내지 않는다.
HTTP 요청 메시지 본문(Body)에 담겨서 전송이 된다.
프론트에서 폼 데이터를 입력하고 제출 시 HTTP 요청 본문에 담겨 서버로 보내짐
JSON형태의 데이터를 본문에 담아 보내는것이 일반적
주로 데이터 생성 or 업데이트 할 때 사용됨
@RequestParam
클라이언트에서 보내오는 요청을 받아낼 때 사용한다. (? 뒤에 오는 값들)
보통 메서드 매개변수에 사용한다.
개별 파라미터 값을 메소드의 단일 인자에 바인딩시 사용한다.
@GetMapping("req/get")
// 리퀘스트 파람 뒤에 받고싶은 명칭
// requestParam사용시 값 넣어서 처리 가능
public String get(@RequestParam) Integer page,
@RequestParam() String search) {
return String.format("%s페이지 %s", page, search);
}
만약에
http://localhost:8080/req/get?search=dog
요청값을 이렇게 보냈다고 하자
그럼 어떻게 나올까?
브라우저에 이렇게 Required parameter page가 없다고 뜬다.
그럼 RequestParam안에 있는 매개변수를 입력해주면 어떻게 될까?
@GetMapping("req/get")
// 리퀘스트 파람 뒤에 받고싶은 명칭
// requestParam사용시 값 넣어서 처리 가능
public String get( /*HttpSession session*/@RequestParam(required = false, defaultValue = "") Integer page,
@RequestParam(required = false, defaultValue = "") String search) {
// session.setAttribute("abcd","1234");
return String.format("%s페이지 %s", page, search);
}
required = false : 해당 요청에 포함되어도 되고, 생략되어도 된다.
defaultValue = " ": 데이터가 생략되었으면 디폴트 벨류를 설정해준다.
http://localhost:8080/req/get
이렇게 요청하면 어떻게 될까?
이렇게 null과 아무런 값이 나오지 않는다.
※null이 나오는 이유: Integer는 참조 자료형이기 때문에 초기값이 null이다. 그래서 아무 값을 입력하지 않으면 null이 출력되는 것을 볼 수 있다.
@ModelAttribute
※@RequestParam과의 차이점@RequestParam: 1:1 로 매핑시키냐@ModelAttribute: 복합객체로 매핑시키냐
이 차이인듯??
여러 파라미터값 즉 복합객체 DTO에 바인딩 할 때 사용한다.
많은 양의 데이터 ex)회원정보, 글 정보 등을 처리할 때 사용한다.
Post방식은 일반 URL에 직접 입력하면 안되고
Postman같이 테스트 프로그램을 사용하면 유용하다.
package com.example;
public class UserDTO {
private String username;
private int userAge;
private String email;
// Spring이 객체를 생성하고 데이터를 주입할 때 필요합니다.
// (기본 생성자는 필수)
public UserDTO() {
}
// 필드 값을 받는 생성자 (선택 사항이지만 있으면 편리)
public UserDTO(String username, int userAge, String email) {
this.username = username;
this.userAge = userAge;
this.email = email;
}
// Getter 및 Setter 메소드 (Spring이 속성에 접근하고 값을 설정하기 위해 사용)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Post를 위해 임의로 DTO를 만들었다.
@RestController
public class UserController {
@PostMapping("/submit-user-form")
public String handleUserForm(@ModelAttribute UserDTO userdto) {
// @ModelAttribute 어노테이션 덕분에 Spring이 요청 파라미터들을
// UserForm 객체의 필드(username, userAge, email)에 자동으로 바인딩하여
// userForm 인자로 전달해 줍니다.
System.out.println("--- 받은 사용자 정보 ---");
System.out.println("이름: " + userdto.getUsername());
System.out.println("나이: " + userdto.getUserAge());
System.out.println("이메일: " + userdto.getEmail());
System.out.println("---------------------");
// 받은 데이터를 포함한 응답 문자열 반환
return "사용자 정보가 성공적으로 접수되었습니다: " + userdto.toString();
}
/submit-user-form으로 body에 form형식 데이터를 제출시
200OK가 뜨면서 사용자 정보가 성공적으로 접수되었다고 뜬다.
그럼 콘솔에서는 어떻게 뜰까?
이렇게 내가 Postman에서 입력한 값들이 뜨게 된다.
@PostMapping 설명의 확장이라고 보면 된다.
@PathVariable
"/{경로변수}"로 오는 요청을 받을 때 사용하면 유용하다.
경로 변수는 {}(중괄호)로 둘러싸인 값을 나타낼 때 사용된다.
URL경로에서 매개변수값을 추출하여 매개변수에 할당한다.
기본적으로 무조건 값을 가져야하며 값이 없을 시 NULL반환
※주로 상세 조회, 수정, 삭제에서 많이 사용된다.
아래의 코드는 게시판의 상세조회하는 코드이다.
@GetMapping("/board/view/{id}")
public String boardView(
@PathVariable("id") Long id, Model model
) {
Optional<Board> opt = boardRepository.findById(id);
if(opt.isEmpty()){
return "redirect:/board";
}
else{
Board board = opt.get();
model.addAttribute("board", board);
}
return "board/view";
}
해당 경로로 /board/view/2를 받으면 id값이 PathVariable로 들어간다.
그럼 boardRepository Jpa를 이용해서 id로 board에 DB테이블을 매핑한다.
opt가 비어있으면 다시 board로 redirection하고
opt에 값이 있으면 board객체에 opt.get()을 이용하여 불러와 넣어준다.
그 후 model.addAttribute로 front에 값을 "board"형식으로 넘겨준다.
※Post 요청 방법
1. HTML의 <form> 태그에 method 속성 사용
ex) <form method="post">
2. JavaScript의 fetch() 함수 사용
ex) fetch('https://api.google.com/user', { method: 'post' })
3. 외부 프로그램 사용
ex) Postman, Talend API Tester
@RequestMapping
RequestMapping은
Get, Post,Put, Delete 모두 지원한다.
요즘에는 잘 안쓴다.
but, 한번씩 클래스에 requestMapping사용시
모든 메소드에 접두어를 공통으로 사용하기위해서
ex) /user클래스의 모든 메소드에 적용 ex)add메소드,list메소드
/user/add /user/list
와같이 유용하게 사용된다.
@RequesMapping(value= "/jpa")와 같이 붙여주면 /jpa/add나 이렇게 할 수 있다.
@ResponseBody
메소드에서 생존하는 어노테이션이다.
@Controller는 메소드가 문자열 등을 반환하면 View는 기본적으로 이름을 해석하여 html파일을 랜더링하여 응답본문에 담아 보낸다.
BUT
@ResponseBody어노테이션을 사용하면 메소드의 반환값을 HTTP 응답의 Body로 직접 전송하는 어노테이션이다.
package com.example.basic.model;
import lombok.Getter;
import lombok.Setter;
//스프링이 실행될 때
//Java 컴파일러가 컴파일 할 때때
@Setter
@Getter
public class Member {
String name;
public Member(){
}
public Member(String name){
this.name = name;
}
}
Member 클래스를 생성하고 Getter와 Setter로 생성자 생성한다.
@GetMapping("json1/list")
@ResponseBody
public List<Member> jsonList() {
List<Member> list = new ArrayList<>();
// List에 멤버 저장시
Member member = new Member();
member.setName("KIM");
list.add(member);
// 생성자 클래스에 만들면 한줄로 바꿀 수 있다
list.add(new Member("Lee"));
return list;
}
ResponseBody에 담아서 list리턴시 어떻게 뜰까?
이렇게 List형식안에 JSON으로 나오는 것을 확인할 수 있다.
여기서 tip
그럼 RestController하나쓰는것과 Controller + ResponseBody를 같이사용하면 같아지는 것이다.
@RequestBody
중간에 스프링이 개입을 해서 텍스트를 JSON형태로 convert해주는 MessageConverter이다.
리액트와 통신할 때 주로 사용 JSON 형태의 데이터라고 생각하면 쉽다.
HTML 템플릿 응답
String
@Controller
public class HtmlController {
@GetMapping("html/string")
public String htmlString() {
return "html/string";
}
}
string.html을 찾아서 랜더링 한다.
Map
@GetMapping("json1/map")
@ResponseBody
public Map<String, Object> jsonMap(Map<String, Object> map) {
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("key1", "value");
map2.put("key2", 2324);
map2.put("key3", true);
return map2;
}
List, Object DTO들은 다 메소드의 리턴타입만 바꿔주기만 하면된다.
@HttpServletRequest
가장 전통적으로 사용되는 요청처리방식이다.
@RestController
public class RequestController {
@GetMapping("req/http")
public String http(HttpServletRequest request) {
String name = request.getParameter("name");
String pageNum = request.getParameter("pageNum");
return name + ", " + pageNum;
}
}
HttpServletRequest 클래스 request객체를 파라미터로 받는다.
그 후 request객체의 메서드 getParameter로 값을 받아서 웹 브라우저에 띄워준다.
응답처리 요약
1.HTML
- @Controller + String
2.JSON
- @Controller + @ResponseBody + (Map/List/DTO)
- @RestController + (Map/List/DTO)
'Spring' 카테고리의 다른 글
[스프링 부트] -Spring JDBC (1) | 2025.04.25 |
---|---|
[스프링 부트] - AJAX 요청 파라미터 전달 (1) | 2025.04.24 |
[스프링부트] - 컨트롤러와 어노테이션들 (0) | 2025.04.22 |
[스프링부트] - DI, IoC 와 Bean (0) | 2025.04.22 |
[스프링부트] - Maven 개발환경 준비하기 feat. VSCode (1) | 2025.04.22 |