국비학원 40일차 : Spring Boot_2

Digeut·2023년 4월 20일
0

국비학원

목록 보기
34/44

Controller

Spring 레이어드 아키텍처에서 프레젠테이션 영역에 해당

상황에 따라 유저 인터페이스 계층이라고도 한다. 클라이언트와의 접점이 된다. 클라이언트로부터 데이터와 함께 요청을 받고 처리 결과를 응답으로 전달하는 역할이다.

MVC 패턴에서 컨트롤러(Controller)는 모델(Model)과 뷰(View)의 중간 영역에 위치하며, 클라이언트의 요청(Request)을 처리하여 모델의 상태를 변경하는 역할을 담당합니다. 컨트롤러가 클라이언트의 요청에 따라 모델의 상태를 변경하는 영역이라는 것은, 컨트롤러가 클라이언트로부터 전달받은 요청(Request)을 처리하여, 필요한 데이터를 모델에 전달하거나 모델의 데이터를 변경하는 역할을 수행한다는 것을 의미합니다.

예를 들어, 사용자가 웹 브라우저를 통해 로그인을 시도하면, 컨트롤러는 로그인 정보를 검증하고, 검증 결과에 따라 로그인이 성공했을 경우에는 모델에 로그인 정보를 저장합니다. 이후 사용자의 요청에 따라 모델의 상태가 변경되며, 변경된 모델의 상태에 따라 뷰(View)가 업데이트되어 사용자에게 결과를 보여줍니다.

따라서, 컨트롤러는 웹 어플리케이션에서 중요한 역할을 담당하는데, 클라이언트의 요청을 처리하고, 그에 따라 모델의 상태를 변경하여 웹 어플리케이션의 동작을 제어합니다.

Model & View

Spring Boot에서 모델(Model)과 뷰(View)는 웹 어플리케이션의 화면을 구성하는 중요한 요소입니다.

모델은 웹 어플리케이션에서 사용되는 데이터나 상태를 의미합니다. 컨트롤러(Controller)에서 처리된 데이터나 상태는 모델에 저장되어 뷰(View)에서 사용됩니다. 모델은 데이터를 저장하는 객체나 변수를 말하며, 컨트롤러가 모델에 저장하는 데이터는 다양한 형태일 수 있습니다. 예를 들어, 회원가입 폼에서 입력한 데이터, DB에서 조회한 데이터, 계산 결과 등이 모델에 저장될 수 있습니다.

뷰는 모델에 저장된 데이터나 상태를 사용하여 화면을 구성하는 역할을 합니다. 뷰는 사용자가 보는 화면을 말하며, HTML, CSS, JavaScript 등으로 작성됩니다. 뷰는 모델에 저장된 데이터를 참조하여 화면을 그리므로, 모델과 뷰는 서로 밀접한 관계를 가지고 있습니다.

컨트롤러는 모델과 뷰를 중개하는 역할을 합니다. 컨트롤러는 클라이언트의 요청(Request)을 처리하여, 필요한 데이터를 모델에 전달하거나 모델의 데이터를 변경합니다. 그리고 변경된 모델의 데이터를 뷰에 전달하여, 화면을 구성합니다. 따라서, 모델과 뷰는 컨트롤러와 함께 웹 어플리케이션에서 끊임없이 상호작용하면서 사용자에게 보여질 최종 화면을 구성하게 됩니다.

Controller Annotation

@Controller

MVC 패턴에서 컨트롤러(Controller)를 정의할 때 사용되는 어노테이션

@Controller
public class RestAPIController {
    
    @RequestMapping(method = {RequestMethod.GET}, value = "hello2") 
 
    public String hello2(){
        return "hello2";
    }


@Controller의 경우 html만을 반환하기때문에 500오류(5XX의 오류는 서버에서 클라이언트 요청을 처리하는 과정에서 오류가 발생한 경우)가 뜨게 된다.

@Controller + @ResponseBody

@ResponseBody

컨트롤러에서 리턴하는 데이터를 HTTP 응답(Response) 본문에 넣을 때 사용하는 어노테이션

@Controller
public class RestAPIController {
    
    @RequestMapping(method = {RequestMethod.GET}, value = "hello2") 
 	@ResponseBody
    public String hello2(){
        return "hello2";
    }


@ResponseBody까지 사용해서 HTTP 응답 본문에 hello를 넣어서 보여줄수 있게 된다.

@RestController

@Controller + @ResponseBody을 한번에 할수 있는 어노테이션

컨트롤러를 정의할 때 RESTful API를 개발하는 데 유용하게 사용됩니다. 즉, @RestController 어노테이션을 사용하여 컨트롤러를 정의하면, 컨트롤러에서 리턴하는 데이터가 JSON, XML 등의 형식으로 바로 HTTP 응답 본문에 넣어지게 됩니다.

@RestController 
//Rest API를 위한 Controller임을 명시해주는 어노테이션
// @Controller + @ResponseBody = @RestController
//Response는 html을 제외한 Mime 타입을 반환한다
@RequestMapping(value = "api") 
//클래스에 패턴을 지정해두면 클래스에서 작업을 하겠다는걸 지칭할수 있다.
// URL path 패턴을 지정해서 해당 패턴이면 지정한 클래스로 처리하도록 함              
//value만 지정할거면 api만 적어도 된다
public class RestAPIController {
    
    @RequestMapping(method = {RequestMethod.GET}, value = "hello2") 
    //가독성떨어짐 → 하나하나 기능별로 분해해서 사용하게된다 Request Method
    //패스가 hello2인 것을 메서드를 겟할수있다..?
    //@ResponseBody 
    // 이 반환해주는 값을 body에 직접 받겠다는 어노테이션
    //메서드에 값을 지정해두면 엔드포인트로 올때 처리해주겠다는걸 지정해주는것
    public String hello2(){
        return "hello2";
    }

//Response는 html을 제외한 Mime 타입을 반환한다❔

@ResponseBody 어노테이션은 Spring MVC에서 컨트롤러 메소드가 반환하는 객체를 HTTP 응답 본문에 직접 작성하는 것을 나타냅니다. 이때 HTTP 응답 본문의 Mime 타입은 컨트롤러 메소드가 반환하는 객체의 타입에 따라 결정됩니다.

즉, @ResponseBody 어노테이션이 붙은 컨트롤러 메소드에서 리턴하는 객체의 타입이 문자열(String)이면, HTTP 응답 본문의 Mime 타입은 text/plain으로 설정됩니다. 반면에, 컨트롤러 메소드에서 리턴하는 객체의 타입이 JSON이면, HTTP 응답 본문의 Mime 타입은 application/json으로 설정됩니다.

@ResponseBody 어노테이션이 붙은 컨트롤러 메소드에서 반환할 수 있는 Mime 타입은 HTML을 제외한 다른 타입들입니다. 즉, HTTP 응답 본문에 직접 작성하는 것이 가능한 타입들로 제한됩니다. 이를테면, JSON, XML, PDF, 이미지 등이 해당됩니다.

HTML을 반환하려면, Thymeleaf 같은 뷰 템플릿 엔진을 사용하거나, ResponseEntity 객체를 사용하여 HTTP 응답의 Mime 타입을 text/html로 설정할 수 있습니다.

MIME 타입❔

MIME(Multipurpose Internet Mail Extensions) 타입은 인터넷 상에서 파일의 확장자에 따라 파일의 형식을 결정하는 방법입니다. MIME 타입은 웹 브라우저가 어떤 형식의 파일인지 인식할 수 있도록 해주며, 해당 파일이 웹 페이지에 포함되어 있는 경우, 브라우저가 이를 적절하게 해석하여 렌더링할 수 있게 합니다.

예를 들어, 웹 서버에서 HTML 파일을 전송할 때는 "text/html"의 MIME 타입을 설정하여 전송합니다. 만약 이미지 파일을 전송할 때는 "image/png" 또는 "image/jpeg" 등의 MIME 타입을 설정하여 전송합니다. 이렇게 MIME 타입을 설정하면, 클라이언트 웹 브라우저는 해당 파일이 어떤 형식인지 인식하여 적절하게 처리하게 됩니다.

Spring Framework에서는 MIME 타입을 지정하는 방법으로, @RequestMapping 어노테이션의 produces 속성이나, @ResponseBody 어노테이션을 사용할 수 있습니다. produces 속성은 컨트롤러 메서드에서 생성된 응답의 MIME 타입을 지정할 수 있으며, @ResponseBody 어노테이션은 메서드의 반환값을 HTTP 응답 본문에 직접 작성할 때 사용되며, 반환값의 MIME 타입을 결정합니다.

@RequestMapping

@RequestMapping은 Spring Framework에서 컨트롤러 클래스나 컨트롤러 메소드에 매핑 정보를 제공하는 어노테이션입니다.

컨트롤러 클래스에 @RequestMapping 어노테이션이 지정되어 있으면, 해당 클래스의 모든 핸들러 메소드는 @RequestMapping 어노테이션이 지정된 URI 패턴에 응답합니다.

컨트롤러 메소드에 @RequestMapping 어노테이션이 지정되어 있으면, 해당 메소드는 URI 패턴에 응답하며, HTTP 요청 방법(GET, POST, PUT, DELETE 등)과 MIME 타입 등을 지정할 수 있습니다. 또한, URI 패턴 내에서 파라미터를 추출할 수도 있습니다.

@RequestMapping 어노테이션은 value 속성을 사용하여 URI 패턴을 지정할 수 있습니다. value 속성은 문자열 또는 문자열 배열로 지정할 수 있으며, 여러 URI 패턴을 지정할 경우 중괄호({})로 묶어서 지정할 수도 있습니다.

@RequestMapping의 속성

- 🌺value: 매핑할 URL 패턴
- ☘️method: 매핑할 HTTP 메서드
- params: 매핑할 요청의 파라미터
- headers: 매핑할 요청의 헤더
- consumes: 매핑할 요청의 본문 MIME 타입
- produces: 매핑할 요청의 응답 본문 MIME 타입

@Controller
@RequestMapping("/users")
public class UserController {

    @RequestMapping(🌺value = "/{id}", ☘️method = RequestMethod.GET)
    public String getUser(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(🌺value = "/add", ☘️method = RequestMethod.POST)
    public String addUser(@ModelAttribute User user) {
        // ...
    }

    // ...
}

위 예제에서는 "/users" URI 패턴에 대한 요청을 처리하는 UserController 클래스를 정의하였습니다. getUser 메소드는 "/users/{id}" URI 패턴에 대한 GET 요청을 처리하며, addUser 메소드는 "/users/add" URI 패턴에 대한 POST 요청을 처리합니다. 이렇게 @RequestMapping 어노테이션을 사용하여 URI 패턴을 지정하면, 해당 URI 패턴에 대한 요청이 컨트롤러의 핸들러 메소드에 매핑되어 처리됩니다.

@RestController 
@RequestMapping(value = ⭐"api") 
//클래스에 패턴을 지정해두면 클래스에서 작업을 하겠다는걸 지칭할수 있다.
// URL path 패턴을 지정해서 해당 패턴이면 지정한 클래스로 처리하도록 함              
//value만 지정할거면 api만 적어도 된다
public class RestAPIController {
    
    @RequestMapping(method = {RequestMethod.GET}, value = ⭐"hello2") 
    //가독성떨어짐 → 하나하나 기능별로 분해해서 사용하게된다 → Request Method
    //패스가 hello2인 것을 메서드를 겟할수있다..?
    //메서드에 값을 지정해두면 엔드포인트로 올때 처리해주겠다는걸 지정해주는것
    public String hello2(){
        return "hello2";
    }

Request Method

@RequestMapping의 기능을 세세히 나눠서 코드를 깔끔하게 한다.
다 따로따로 관리할수 있게 해줄 수 있다.

//GET method @GETMapping
// 클라이언트가 서버에게 데이터를 받기위한 요청의 Method
// 사용자 정보를 요구하는 상황에서 사용함.
// @RequestMapping(mehod=RequestMethod.GET, value="get-mdthod")과 동일.
@GetMapping("get-method") 
//패스를 지정해준것 (path value)
//프로그래밍 언어에서는 띄어쓰기할때 '_' 하거나 
//각각 카멜케이스쓰는데 url표시할때는 -으로 표시하게 된다
    public String getMethod(){
        return "Response of Get Request";
    }

//POST Method @PostMapping
// 클라이언트가 서버에 데이터를 작성하기 위한 요청의 Method
 // @RequestMapping(mehod=RequestMethod.POST, value="post-mdthod")과 동일.
@PostMapping("post-method") 
//리소스는 있는데 POST로만 인식되게 해둠. 
//다른 걸 사용하면 405에러가 뜬다
//리소스는 찾았는데 대응하는 메서드를 찾지못했다고 뜨게된다.
    public String postMethod(){
        return "Response of Post Request";
    }


POST 메서드가 아닌 GET 메서드로 지정하고 실행시 405의 오류가 뜬다
리소스는 찾았는데 대응하는 메서드를 찾지못했다고 뜨게된다.

//Patch Method @PatchMaping
// 클라이언트가 서버에 데이터를 '일부'만 수정하기 위한 요청의 mehod 
//put은 전체를 수정하게된다
// @RequestMapping(mehod=RequestMethod.PATCH, value="patch-mdthod")과 동일.
@PatchMapping("patch-method")
    public String patchMethod(){
        return "Response of Patch Requset";
    }

//Delete Method @DeleteMapping
// 클라이언트가 서버에 데이터를 삭제하기 위한 요청의 method
//@RequestMapping(mehod=RequestMethod.DELETE, value="delete-mdthod")과 동일.
    @DeleteMapping("delete-method")
    public String deleteMethod(){
        return "Response of Delete Request";
    }

Patch

patch의 경우 성공 또는 실패만 반환하면 되기때문에 굳이 body에 값을 가질 필요없다는 뜻이다.
Delete

Delete의 경우 삭제이기때문에 body에 굳이 값을 가질 필요가 없다는 뜻.

Request Data (Parameter)

@PathVariable

@PathVariable 어노테이션을 사용하면 URI 패턴에서 추출한 변수를 메소드 매개변수로 사용할 수 있으며, 해당 변수를 사용하여 비즈니스 로직을 수행한 후 View에 전달할 수 있다.

Get, Delete Method에서 요청시 데이터를 전송받는 방식이다. path 자체를 데이터로 받아오는 방법이다.

//*PathVariable()로 Get, Delete Method에서 데이터 받기
// 리소스에 지정한 패턴에 따라 맞춰서 요청의 url을 지정한다면
// 패턴에 맞춰 데이터를 받아오는 형식
@GetMapping("path-variable/{data1}/{data2}") 
			//{}안의 값은 내가 입력하는것
public String pathVariable(
	@PathVariable(value="data1") String dataA,
    /*data1만 입력해도 된다. 입력값이 1개일 경우에는*/
	@PathVariable(value="data2") String dataB
	){
        return dataA + dataB + " 데이터를 입력받았습니다.";
    }

데이터 2개를 받고자 path지정해두고 1개의 데이터만 입력시 오류

🤔400번대의 오류가 발생
→ 데이터 하나만 받아서 만드는 걸 따로 만들어서 처리를 해줄수도 있고,
안의 들어가는 코드가 완전히 똑같다면 @GetMapping자리에 받을수 있는 value를 문자열의 배열로 들어가서 2개이상 들어가게 할 수 있다.
{"path-variable/{data1}/{data2}","path-variable/{data1}" 둘중하나를 만족하면 반환되도록해주는것

데이터 1개 또는 2개를 받을 수 있도록 지정했을때

 @GetMapping({"path-variable/{data1}/{data2}"}) 
 			//{}안의 값은 내가 입력하는것
    public String pathVariable(
        @PathVariable(value="data1") String dataA,
        @PathVariable(value="data2") String dataB
        ){
        return dataA + dataB + " 데이터를 입력받았습니다.";
    }


🤔예외처리를 안해줘서 500오류가 뜨게된다
→required = false추가하면 null값으로 들어가서 반환되게 된다.

최종 해결

@GetMapping({"path-variable/{data1}","path-variable/{data1}/{data2}"}) 
						//{}안의 값은 내가 입력하는것
    public String pathVariable(
        @PathVariable(value="data1") String dataA,
        @PathVariable(value="data2", required = false) String dataB
        ){
        return dataA + dataB + " 데이터를 입력받았습니다.";
    }


둘 이상의 데이터가 입력 가능하게 한 뒤, 두번째 데이터의 required를 false로 지정해서 null값이 반환되도록 해주었다.

@RequestParam

Get, Delete Method에서 요청시 데이터를 전송받는 방식이다. path에 데이터를 추가하여 받아오는 방법이다.

Get Method와 Delete Method는 데이터를 전송하고자 할때 Request Header의 URL에 데이터를 포함하여 전송해야 하는데 이때 path 뒤에 ?name1=value1&name2=value2 형식으로 name과 value를 명시하여 전송하는 형식이다.

//*@RequestParam 로 GET과 DELETE Method에서 데이터 받기
// 완전한 path 뒤에 ?name=value[&...] 형식에 맞춰 
// name에 해당하는 value를 받아오는 형식
// '?'뒤로는 '데이터'의 포맷으로 인식을 한다, path가 아니다! 
@GetMapping("request-param")
public String requestParam(
	@RequestParam String data1, 
    //data이름을 바꾸게되면 url지정 이름도 바꿔줘야한다
	@RequestParam String data2
	
){
	return data1 + data2 + " 데이터를 입력받았습니다.";
	
    } 

data의 형식을 보면 key와 value의 형태 하나의 묶음으로 넘어온것 = 오브젝트, 객체! → 객체로도 받을수 있다는 말이 된다.

객체로 데이터 받아오기

class ParamDto {
    private String data1;
    private String data2;

    public String getData1(){
        return this.data1;
    }

    public String getData2(){
        return this.data2;
    }

    public void setData1(String data1){
        this.data1 = data1;
    }

    public void setData2(String data2){
        this.data2 = data2;
    }
}

@GetMapping("request-param")
public String requestParam(
	@RequestParam ParamDto dto
){
	return dto.getData1() + dto.getData2() + " 데이터를 입력받았습니다.";
// get의 경우 url에 데이터가 노출이 될수 있으므로 
//필수적인 정보를 담기에는 보안상 위험하다
    } 

🤔데이터 입력 관련 문제라서 400의 오류가 뜬다

@PathVariable & @RequestParam()의 차이

순서의 유무! @RequestParam에는 순서가 필요하지 않게된다.
name을 정해버리기때문에 웹서버상에 리퀘스트 요청시에 많이 쓰이게 된다

@RequestBody

Post, Put, Patch Method에서 요청시 데이터를 전송받는 방식이다. Request Body 데이터를 포함하여 전송하는데 이때는 JSON 형태의 데이터 포멧을 이용해 객체로 데이터를 받거나 문자열로 데이터를 받을 수 있다.

Controller에서 전송한 데이터를 받기 위해서는 객체 혹은 문자열로 받아야 한다.

문자로 받을때

//* @RequsetBody로 Post, Put, Patch Method에서 데이터 받기
// Request Body에 있는 데이터를 받기 위한 어노테이션
@PostMapping("request-body")
public String requestBody(
	@RequestBody String data //문자로 받을때
){ 
	return data1 + data2 + "데이터를 받았습니다";
    }
}

객체로 받을때

//* @RequsetBody로 Post, Put, Patch Method에서 데이터 받기
// Request Body에 있는 데이터를 받기 위한 어노테이션
@PostMapping("request-body")
public ResponseEntity<ParamDto> requestBody(
        
	@RequestBody ParamDto dto //객체로 받을때
    //dto로 받을때는 필수로 지정되어있지 않기때문에 null로 받을수는 있다
	// 필수로 받고자 할때는 validate이용해서 사용할수 있게된다.
    ){ 
	return ResponseEntity.status(408).body(dto);
    //.getData1() + dto.getData2() + "데이터를 받았습니다";
    }

ResponseEntity

Response의 헤더, 응답 코드, 상태 및 데이터를 포함하여 반환할 수 있도록 해주는 클래스이다. 데이터 뿐만 아니라 헤더, 응답 코드, 상태를 포함하여 전송할 수 있다는 장점 때문에 REST API에서 유용하게 사용된다.

return ResponseEntity.status(408).body(dto);


지정한 상태로 status가 결정되게 된다.

ViewResolver

viewResolver는 Spring Framework에서 사용되는 클래스 중 하나로, 컨트롤러에서 반환된 뷰 이름을 실제로 사용할 뷰로 변환해주는 역할을 합니다.

Spring MVC에서는 컨트롤러에서 처리한 결과를 뷰(View)로 보여주어야 하는데, 이때 컨트롤러에서 반환한 뷰 이름은 실제 뷰와 일치하지 않을 수 있습니다. 이런 경우에 viewResolver는 뷰 이름을 실제 뷰의 경로로 변환하여 해당 뷰를 찾아 보여줄 수 있게 도와줍니다.

ViewResolver는 설정 파일에서 등록할 수 있으며, 다양한 종류의 ViewResolver가 제공됩니다. 가장 기본적인 InternalResourceViewResolver는 JSP나 Thymeleaf와 같은 템플릿 엔진을 사용하는 경우에 많이 사용되며, 다른 ViewResolver를 사용하여 JSON, XML, PDF 등 다양한 형식의 뷰도 처리할 수 있습니다.

profile
개발자가 될 거야!

0개의 댓글