배움 __IL/TIL 1기

TIL : 58번째- 230224 [2-3-금]

Mo_bi!e 2023. 2. 24. 19:00

I. 들어가며 

프론트 컨트롤러는 스프링부트가 하고

우리가 하는것은 컨트롤러 부분의 pojo 이다!

II. 웹개발

1. 뷰 단에 보내주기 즉 컨트롤러에서 출력하기

1)

 

*아웃(풋) 파라미터 : 반환 값을 받기위한 방식 중 하나

일반적으로 함수는 리턴만 반환뿐만 아니라 빈그릇주고, 빈그릇같이 쓰는것 만(Model model)으로 반환이 가능하다.

 

2)

서블릿 계속 들게(request) 하면 프론트 컨트롤러 의미없어짐

서블릿 아닌 그릇(model)준비해서 담기(addAttribute)!

 

원룸에서 투룸살면은 방마다 용도 정해놓는것인데, 막쓰면 정한 의미가 없다

 

3)

스프링이 Model을 이용해서 model에 값을 채우면 전달이된다

 

package kr.co.rland.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class homeController {

	@RequestMapping("/index")
	public String index(Model model) {
		
		String data = "Hello Data";
		
	
		model.addAttribute("data",data);
		
		
		return "/WEB-INF/index/index.jsp";
//		return "hello";
		
	} 

}

model 에 값을 채우고 전달

 

<index.jsp>

<body>

	<h1>welcom rland : ${data}</h1>
	
</body>

index.jsp 에서 전달받은 값을 출력함

 

 

(2) 뷰 입력받는 것 처리하기

1)

<list.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
   
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
   
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h1>admin 메뉴 목록 페이지</h1>
	
	<nav>
		<h1>페이저</h1>
		<ul>
		<c:forEach var="n" begin="1" end="5">
			<li><a href="index?p=1&q=hello">${n}</a></li>
		</c:forEach>
		</ul>
	</nav>

</body>
</html>

EL / JSTL 을 쓰자

이 경우 버전을 잘 맞추어 주어야한다 (api 와 구현 둘다 pom.xml 넣어주기)

 

2)

@GetMapping("list")
public String list(int p, String q) {

    System.out.println(p + " "+q);

    return "/WEB-INF/view/admin/menu/list.jsp";
}
<nav>
    <h1>페이저</h1>
    <form>
        <label>size:</label>
        <!-- <input name="s" value="10"> -->
        <select name="s">
            <option value="10">10</option>
            <option value="20">20</option>
            <option value="50">50</option>
        </select>

        <input type="submit" value="변경">


    </form>


    <ul>
    <c:forEach var="n" begin="1" end="5">
        <li><a href="list?p=${n}&q=hello">${n}</a></li>
    </c:forEach>
    </ul>
</nav>

입력을 함수가 받는것처럼 파라미터로 넣을수있다

알아서! 잘! 들어온다

 

이런경우

뷰 페이지 에서 1,2,3,4,5 태그를 클릭하면 콘솔에 쿼리스트링의 특정 값이 컨트롤러로 전달된다.

 

 

3)

사실 매개변수에서 정수로 받을수는 없고 어떤경우도 문자열로 받아야해

null 오류가 뜨는건 int 자료형이기 때문이야

- String으로 받고나서 유효성 체크하고 parseInt 로 가능해

어노테이션은 설정인데 기본값 설정하면 null에 대해서 해결이 가능해

@GetMapping("list")
public String list(
        @RequestParam(name ="p", defaultValue = "1") int page,
        @RequestParam("q") String query
        ) {
        System.out.println(page + " "+query);

        return "/WEB-INF/view/admin/menu/list.jsp";
    }

앞서 자료형 int 에 대한 defaultValue=1  을 넣으면 null 로 전달되는 것이 1로 대입되어서 해결이 가능하다

 

@RequestParam 의 경우 가장 기본적인 형태는 ("p") 단 하나만 넣으면된다

다만 name, default 가 있는 경우에는 그 명칭을 함께 넣어주어야한다

 

==

그리고 이경우 q 에 전달값이 없는경우 400에러가 뜬다

@RequestParam(name ="p", defaultValue = "1") int page,
@RequestParam(name = "q", required = false) String query
) {

본 어노테이션하면 파라미터 받을 준비는 하지만 오지 않아서 오류가 발생한다

이 경우 required=false 하면 해결이된다

 

 

(3) 쿠키로부터 값 받아오기

1)

쿠키는 서블릿꺼야 그리고 보낼 때 response 로 보내야 해! 스프링부터에서 지원이 안돼서 어쩔 수 없다...

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;

@Controller
public class homeController {

  @RequestMapping("/index")
    public String index(Model model, HttpServletResponse response) 
    	throws UnsupportedEncodingException {
        
        //String data = "Hello Data";
        
        String data = URLEncoder.encode("cookie 지롱~", "utf-8");
        System.out.println(data);
        Cookie cookie = new Cookie("my", data);
        response.addCookie(cookie);
        
        //model에는 addAttribute이다.
        model.addAttribute("data", data);
        
        return "/WEB-INF/index/index.jsp";
    }

할수 없이 두가지를 이용했다.

 

 

+

String data = URLEncoder.encode("cookie 지롱~", "utf-8");
System.out.println(data);
String data2 = URLDecoder.decode(data, "utf-8");
System.out.println(data2);

: 인코딩 결과 / 아래 : 인코딩한 것을 다시 디코딩 한 경우

이렇게 인코딩 하는 이유는 [cookie 지롱~] 에서 스페이스바 ~ url 이 읽을 수 있게끔 하기 위해서 이다

이후 url 이 다읽으면 디코딩을 다시하면 원래의 상태로 돌아온다

index 의 Set-Cookie

 

2)

@GetMapping("list")
public String list(
        @RequestParam(name ="p", defaultValue = "1") int page,
        @RequestParam(name = "q", required = false) String query,
        HttpServletRequest request
        ) {
        System.out.println(page + " "+query);

        String myCookie = "";
        Cookie[] cookies = request.getCookies();

        for(Cookie cookie : cookies)
            if(cookie.getName().equals("my")) {
                myCookie = cookie.getValue();
                break;
            }

        System.out.println(myCookie);
        System.out.printf("page :%d, query:%s\n", page,query);


        return "/WEB-INF/view/admin/menu/list.jsp";
    }

index 에서 add 한 쿠키를 list 에서 get 을 한다.

 

get한 Cookie 중에서 이름(key값)이 my 인 부분의 값을 받아와서 myCookie 에 대입한다

이 값을 출력한다

 

 

+

for(int i = 0 ; i< cookies.length ; i++) {
        System.out.println(cookies[i]);
    }

콘솔출력
list 의 Cookie

쿠키는 두개가 있는 상태이다 myCookie내가 직접 지정한 쿠키이다

 

3)

그런데 이렇게 필요한 쿠키를 뽑아주기위해서 get 하는등의 과정을 거칠필요가 전혀없다.

스프링부트는 자동으로 다해주며 인코딩까지도  해준다

@GetMapping("list")
	public String list(
			@RequestParam(name ="p", defaultValue = "1") int page,
			@RequestParam(name = "q", required = false) String query,
			@CookieValue("my") String myCookie
//			HttpServletRequest request
			) {
			System.out.println(page + " "+query);
			
//			String myCookie = "";
//			Cookie[] cookies = request.getCookies();
//			
//			for(Cookie cookie : cookies)
//				if(cookie.getName().equals("my")) {
//					myCookie = cookie.getValue();
//					break;
//				}
			
			System.out.println(myCookie);
			System.out.printf("page :%d, query:%s\n", page,query);

@CookieValue 하면 된다.

이런경우 디코딩이 덜 된 것이다 그래서 '+' 가 들어가있다. 

 

+ 직접 디코딩하면 

@GetMapping("list")
public String list(
        @RequestParam(name ="p", defaultValue = "1") int page,
        @RequestParam(name = "q", required = false) String query,
        @CookieValue("my") String myCookie
//			HttpServletRequest request
        ) throws UnsupportedEncodingException {
        System.out.println(page + " "+query);

//			String myCookie = "";
//			Cookie[] cookies = request.getCookies();
//			
//			for(Cookie cookie : cookies)
//				if(cookie.getName().equals("my")) {
//					myCookie = cookie.getValue();
//					break;
//				}

        myCookie = URLDecoder.decode(myCookie, "utf-8");

        System.out.println(myCookie);
        System.out.printf("page :%d, query:%s\n", page,query);

 

중점 : 스프링 프론트컨트롤러가 얼마나 편한지가 중요해!

 

 

(4) 헤더

1)

헤더에는 다양한 정보가 있다

이 중에서 어디를 경유해서  들어오는지 등이 있다

이 또한 서블릿과 달리 간편하게 가능하다.

 

2)

@GetMapping("list")
	public String list(
			@RequestParam(name ="p", defaultValue = "1") int page,
			@RequestParam(name = "q", required = false) String query,
			@CookieValue("my") String myCookie,
			@RequestHeader("Accept-Language") String language

			) throws UnsupportedEncodingException {
			System.out.println(page + " "+query);
			
			System.out.printf("Landuage : %s \n",language);

이런 방식으로 어떤 언어로 설정되어있는지 확인이 가능하다.

 

(5) 파일업로드

1)

업로드방법은 3가지이다

1 클라이언트가 파일업로드 하는 방식은 선택 상자에서 클릭해서 하는 방법

2 드래그 드랍

3 클립보드 이용한 컨+C V

 

2)

<homeController.java>

@Controller
@RequestMapping("/")
public class homeController {
	
	@PostMapping("upload")
	public String upload() {
		
		System.out.println(img.getOriginalFilename());
		
		return "ok";
		
	}

return "ok" 

즉 upload 를 완료하면 ok를 출력되게끔 했다.

 

<reg.jsp> 에 이미지 파일을 받을 수 있는 방식으로 작성한다.

<section>
    <h1>메뉴 등록 페이지 </h1>
    <form method="post">
        <fieldset>
            <legend>메뉴 입력 필드</legend>
            <div>
                <label>제목 : </label>
                <input type="text" name="title">
            </div>
            <div>
                <input type="submit" value="등록">
            </div>				
        </fieldset>
    </form>

    <form action="/upload" method="post">
        <fieldset>
            <legend>파일 입력 필드</legend>
            <div>
                <label>이미지 : </label>
                <input type="file" name="img">
            </div>
            <div>
                <input type="submit" value="등록">
            </div>				
        </fieldset>
    </form>
</section>

이후 파일을 첨부하면 다음과 같은 오류가 뜬다

왜냐하면 본 homeController은 전체적으로 restController이 아니라 Controller이기 때문에 return 은 view 의 경로여야한다

그러나 ok 의 경우 경로가 아니기 때문에 오류가발생한다 그렇다면 restController 해야하나?

불가능하다 (하나 때문에 전체를 바꿀수없다)

 

3)

리턴이 뷰가 아니라 통채로 얘가 body야 라고 알려주는 경우!

@Controller
@RequestMapping("/")
public class homeController {
	
	@PostMapping("upload")
	@ResponseBody
	public String upload() {
		
		return "ok";
		
	}

얘만 restController 하는 것을 지정해주는 방법이다.

 

 

4)

이미지 의 경우 인수의 자료형을 지정해주자 (파일위한 자료형)

@PostMapping("upload")
@ResponseBody
public String upload(MultipartFile img) {

    System.out.println(img);

    return "ok";

}

MultipartFile 형식으로 하면된다. 색다른 자료형이다

그런데 등록을 하면 콘솔에 여전히 null이다

왜냐 바이너리 파일이 아니기 때문이다. 문자열보낸 것은 불가능하다. 

모든 데이터는 url 인코드로 바뀌어서 가는 것이다 (문자열 => url 로 변환해서 보내기)

<form action="/upload" method="post" enctype="multipart/form-data">
    <fieldset>
        <legend>파일 입력 필드</legend>
        <div>
            <label>이미지 : </label>
            <input type="file" name="img">
        </div>
        <div>
            <input type="submit" value="등록">
        </div>				
    </fieldset>
</form>

encodeType 은 다음과 같이 지정해주면 읽을 수있다 (주로 검색해서 찾아보자)

 

 

 

2. 마치며

다음시간 : 파일사이즈, 오류 해결하는 방법

 

==

 

이렇게 입력받는 방법을 보았다

비동기나 동기형이나 같은 방법이여서 하나만 만들면 가능하다

 

 

 

 

 

 


1. 보충

(1) Model 객체

What (정의) : 스프링에 존재하는 객체인데, HashMap 형태로서 key value 값을 가지고 있다. 모델에서 뷰로 값을 전달한다.

Why (존재이유) : Controller 에서 생성된 데이터를 Model 객체에 담아서 View에 전달하기 위해서 사용하는 것 ( Servlet 의 request.setAttribute() 와 유사함)

How (방법) : 함수의 인수에 Model 클래스와 객체를 선언해서 해당 함수 내에서 참조값으로 사용함

e.g. (예) :

 

(1 - 1) Java beans 규칙

Model 객체공부와 관련해서 스프링에서 javaBeans 규칙에 맞는 객체는 파라미터 자동전달이 가능하다고 한다.

여기서 java beans 규칙이란?

 

What (정의) : 클래스의 형태를 의미하는 것으로서 캡슐화(은닉화)형태로 볼 수있다. MVC(C:구조) 부분에 기본 setUp해주던 방식으로 이해할 수있다.

 

Why (존재이유)  : 데이터 표현을 하기 위해서이다. (MVC 중 C) / JSP 는 데이터를 보여주는 기능이 있는데, 보통 javaBean Class 에 담아서 전달한다.

How (방법) :

 

<규약>

- 반드시 클래스는 패키지화 되어야한다

- 멤버변수는 property(프로퍼티)라고 부른다.

- property접근제한자는 private

- 외부접근은 게터세터로 접근한다.

- 프로퍼티가 boolean이면 get이 아니라 is사용해도 된다.

 

(2) MultipartFile

What (정의) : 스프링프레임웍에서 인터페이스인 MultipartFile은 file 을 업로드 기능을 구현하기 위한 것이다. 

Why (존재이유)  : 업로드 기능을 구현하기 위해서

How (방법) : form 태그와 함께 이용한다 +  다음시간에! 

 

(3) entype

What (정의) : form 태그에서 서버에 데이터를 전송할때 인코딩 방법 명시하는 것을 의미한다. 

Why (존재이유) : 파일전송 때 데이터 타입에 따라 지정하지 않는 경우 데이터 전송에 비효율적이기 때문이다.

How (방법) : post 인경우 가능함

 

 

(3) ResponseBody <-> RequestBody

What (정의) :응답본문이라 하며 비동기로 서버 클라이언트간 통신JSON형식으로 서로간에 전송하는 것이다. 

즉 서버에서 클라이언트로 자바객체응답본문객체변환해서 클라이언트로 전송하는 역할을한다.

 

Why (존재이유) : 서버 클라이언트 상호간 전송을 위해서

How (방법) : 어노테이션을 이용한다

 

2. 회고 

1) 확실한건 빠르게 정리하고 추가로 더 공부하는것 만큼 뿌듯한게 없는것 같다.

 

'배움 __IL > TIL 1기' 카테고리의 다른 글

TIL : 61번째- 230302 [2-4-목]  (0) 2023.03.02
TIL : 60번째- 230228 [2-4-화]  (0) 2023.02.28
TIL : 57번째- 230223 [2-3-목]  (0) 2023.02.23
TIL : 56번째- 230222 [2-3-수]  (0) 2023.02.22
TIL : 55번째- 230221 [2-3-화]  (0) 2023.02.21