Spring Boot 3일차

김용진·2023년 9월 22일
0

1. HTTP요청 파라미터

HTTP요청 데이터 조회
스프링이 얼마나 깔끔하고 효율적으로 요청 데이터를 전달하는지 방법을 알아보자

1-1. @RequestParam

  • 스프링이 제공하는 @RequestParam을 사용하면 요청 파라미터를 매우 편리하게 사용할 수 있다.
    @RequestMapping("/request-param-v1")
    	public void requestParamV1(HttpServletRequest request,
    			HttpServletResponse response) throws IOException{
    		String username = request.getParameter("username");
    		int age = Integer.parseInt(request.getParameter("age"));
    		
    		System.out.println("username : " + username);
    		System.out.println("age : " + age);
    		response.getWriter().write("ok");
    	}
    해당 코드를 뜯어보자.. /request-param-v1 주소를 mapping하여 parameter값을 설정하고, 그 값을 저장하고 불러오도록 하는 아주 간단한 작업이다.

포트는 9090을 사용하고있다면 http://localhost:9090/request-param-v1?username=자바&name=20 을 넣는다면 콘솔창에 username : 자바, age = 20이 나올것이고, html은 ok가 뜨는걸 확인할 수 있다.
여기서 @RequestParam 을 이용해서 더 간략하게 바뀌는걸 보여줄거다.

 @RequestMapping("/request-param-v2")
      public String requestParamV2(
              @RequestParam("username") String memberName,
              @RequestParam("age") int memberAge){
          System.out.println("username : " + memberName);
          System.out.println("age : " + memberAge);
          return "ok2";
          // 특이점은 age처럼 int형인것들도 string이 아니라 int로 받아오기에 형변환할 필요가 없다

변수 타입을 지정하던게 사라지는게 보이는가.. 심지어는 cast없이 int를 @RequestParam으로 받아온다...
심지어 HTTP에 이름이 지정한 변수와 이름이 같다면 파라미터를 잡아주는것도 생략이 가능해서 아래 코드처럼 된다

@RequestMapping("/request-param-v3")
	public String requestParamV3(
			@RequestParam String username,
			@RequestParam int age){
		System.out.println("username : " + username);
		System.out.println("age : " + age);
		return "ok3";
	}

여기서 String, int같은 단순 변수면 그냥 변수선언도 안한다.

@RequestMapping("/request-param-v4")
	public String requestParamV4(String username, int age){
		System.out.println("username : " + username);
		System.out.println("age : " + age);
		return "ok4";
	}

이정도면 사기치는정도

위 코드 들은 생긴게 달라보여도 모두 같은 값을 보여준다.
물론 이게 자바 스프링에 한정된 방식이긴하다.

그런데 이제 여기서 한가지 의문점이 생긴다. 바로 변수에 값이 없다면? 인데.. 그래서 1일차에 살짝 언급하고 지나간 required문을 사용한다. required문은 false면 값이 없어도 진행하고 ture면 값이 없으면 호출을 거부한다.

	@ResponseBody
	@RequestMapping("/request-param-required")
	public String requestParamRequired(
		@RequestParam(required = true) String username,
		@RequestParam(required = false)  Integer age){
		System.out.println("username : " + username);
		System.out.println("age : " + age);
		return "required";
	}

int는 값을 넣지 않으면 null값을 받아오기에 int가아니라 Integer를 선언해주는게 포인트, 갑자기 @ResponseBody가 생겨서 저게 뭐지 하시는분이있다면 저건 html로 넘어갈때 return에 쓰여진 값을 보여주게 하는 구문이라고 보시면 될것 같다.

그러면 이제 "어? true면 이제 값이 없으면 무조건 빠꾸(?) 먹는건가 하시겠지만 그런 경우를 위해서 defaultValue가 존재한다.

@RequestParam(required = true, defaultValue = "guest") String username,
@RequestParam(required = false, defaultValue = "-1")  int age)

이렇게 집어넣어주면 값을 부여하지 않더라도 defaultValue에 값이 대신 출력된다. 덤으로 age에 -1이 들어가기 때문에 Integer할 필요없이 int를 써줘도 된다.

사실 이렇게 DefaultValue를 선언 해 주면 required = true를 쓰는 의미도 사라진다... 어차피 기본값은 항상 존재하니까

1-2.@ModelAttribute

전에 사용한 Model model를 기억하시는분이 있을지 모르겠다.. Map<Key, Value>랑 같은 방식인데 이게 어노테이션에도 있다.

	@ResponseBody
	@RequestMapping("/request-param-map")
	public String requestParamMap(
			@RequestParam Map<String, Object> paramMap){
		System.out.println("username : " + paramMap.get("username"));
		System.out.println("age : " + paramMap.get("age"));
		return "map";
	}

여기 이쁜(?) 코드가 있다. key값으로 username, age를 설정하고, 거기에 담겨서 위 주소로 보내면 value를 꺼내 보여준다.

package com.codingbox.core3.basic;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter @Setter @ToString
	public class HelloData {
	private String username;
	private int age;
}

이렇게 HelloData라는 이름의 자바에 Getter, Setter를 설정해주고..

	@ResponseBody
	@RequestMapping("/request-attribute-v1")
	public String requestAttributeV1(
			@RequestParam String username,
			@RequestParam int age){
		HelloData helloData = new HelloData();
		helloData.setUsername(username);
		helloData.setAge(age);
		
		System.out.println("username : " + helloData.getUsername());
		System.out.println("age : " + helloData.getAge());
		return "attr1";
	}

컨트롤러쪽을 요로코롬 해준다면 이클립스, 자바에서흔히 쓰던 문구가 만들어진다.
그런데 여기에 @ModelAttribute 가 들어간다면?

	@ResponseBody
	@RequestMapping("/request-attribute-v2")
	public String requestAttributeV2(
			@ModelAttribute HelloData helloData){
		
		System.out.println("username : " + helloData.getUsername());
		System.out.println("age : " + helloData.getAge());
		System.out.println("helloData : " + helloData.toString());
		return "attr2";
	}

어. @RequestParam이 없다.. setter설정이 없어졌다..

그런데 우리 아까 @RequestParam할 때 단순한 변수형은 생략했는데, 이녀석도 그게 가능하다

		@ResponseBody
		@RequestMapping("/request-attribute-v3")
		public String requestAttributeV3(HelloData helloData){
			System.out.println("username : " + helloData.getUsername());
			System.out.println("age : " + helloData.getAge());
			System.out.println("helloData : " + helloData.toString());
			return "attr3";
		}

@ModelAttribute도 없어진 모습

사실 @ModelAttribute은 없애버리면 코드 리딩이 매우 불친절해져서 이 단계까지는 가지않는다..

그냥 이럴수 있다고만 보고 따라하지는 말자.

2. thymeleaf(타임리프) 특징

2-1. 서버 사이드 HTML 렌더링(SSR)

  • 타임리프는 백엔드 서버에서(jsp처럼) HTML을 동적으로 렌더링 하는 용도로 사용된다.

2-2. 넷츄럴 템플릿

  • 타임리프는 순수 HTML을 최대한 유지하는 특징이있다.
  • 타임리프으로 작성한 파일은 HTML을 유지하기 때문에 웹 브라우저에서 파일을 직접 열어도 내용을 확인할 수 있고, 서버를 통해 뷰 템플릿을 거치면 동적으로 변경된 결과를 확인할 수 있다.
  • 순수 HTML을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 네츄럴 템플릿(natural templates)라 한다.

2-3. 스프링 통합 지원

  • 타임리프는 스프링과 자연스럽게 통합되고, 스프링의 다양한 기능을 편리하게 사용할 수 있게 지원한다.
profile
메모리폼

0개의 댓글