본문 바로가기

백엔드 개발/SpringMVC

@ 어노테이션 전문화, view Controller, Redirection

1. @ RequestMapping의 전문화 

@RequestMapping으로 URL과 컨트롤러를 Mapping 해버리면 사용자는 GetMapping PostMapping 두 방법 다 사용하여 컨트롤러를 이용할 수 있다. 

예를 들어 회원가입 시 GetMapping으로 스트링 쿼리에 회원 가입 내용을 다 적은 채 작성할 수도 있고, PostMapping으로 개인 정보는 전부 body에 넣어 기입 할 수 도 있다. 

당연하지만, GetMapping으로 개인정보를 작성하면 브라우저에 노출되기 때문에 보안적으로 좋지 않다. 

이와 같이 특정 상황에 대해 Getmapping 혹은 PostMapping으로만 컨트롤러와 브라우저가 Mapping 되게 하는 것이 가능하다. 

이에 대해서 논해본다. 

(1) @ RequestMapping의 full 형태

//간소화 버젼
@RequestMapping("/register/add")

// 실제 내용 다 쓴 거 -> method = 두 가지 방법 다 쓸 수 있는게 default 이다.
@RequestMapping(value = "/register/add", method={RequestMethod.GET, RequestMethod.POST})

사실 full 내용을 다 쓴 뒤 method에 접근 가능하게 하고 싶은 REST API 요청이 무엇인지 적는 것으로 위의 문제를 해결할 수 있다. 하지만 이는 코드 치기 복잡하고 번거롭다.

//POST Mapping 으로만 접근 가능하게 하고 싶은 경우
// 이 경우 method = 배열 이 아니라 = 변수 형태로 나타내도 된다.
@RequestMapping(value="/register/add", method=RequestMethod.POST)

(2) @GetMapping, @PostMapping

Spring 4.3부터 업데이트 된 @GetMapping과 @PostMapping 을 이용하면 더 간단하게 표현할 수 있다. 

// GetMapping으로만 해당 url 접근
@GetMapping("/register/add")

// PostMapping으로만 해당 url 접근
@PostMapping("/register/add")

 

**참고** 

만약 당신의 Spring이 4.3보다 버젼이 낮다면 STS나 Intellj에서 업데이트 해줘야 한다. 

먼저 pom.xml 파일을 열어라. (여기가 Spring의 모든 정보가 담긴 Spring의 뇌이다.)

 

속성에서 Spring frameWork-version을 5.0.7로 바꿔라.

그 뒤에 지금 자신이 사용하는 project 누르고 maven > update Project 를 클릭하라. 

그러면 Maven Dependencies의 모든 파일의 버젼이 5.0.7이 된 걸 볼 수 있다.

2. view Controller 

(1) 어느 때 사용? 

사실 저번 예제에서 배운 회원 가입 화면을 띄우는 컨트롤러의 매소드는 하는 역할이 브라우저에서 매핑된 주소를 친 걸 확인하면registerForm.jsp라는 view로 가라고 해주는 것 밖에 없다. 그 외에 다른 기능은 없다.

	@GetMapping("/register/add") // 신규회원 가입 화면
	public String register(){
		return "registerForm";
		
	}

 이런 경우라면, 해당 매소드를 쓰지 않고 /register/add라는 주소를 치면 registerForm으로 가라고 Web-app 전체에 설정하는 것이 가능하다.

(2) 쓰는 법

WebApp > resources > WEB-INF > spring > appServlet > servlet-context.xml 로 들어가면 된다. 

참고로 Servlet-context는 Spring 의 Web관련 설정이고, root-context는 Web 제외 모든 설정을 하는 곳이다. 

 

여기서 맨 마지막에 

	<view-controller path="/register/add" view-name="registerForm"/>

를 치자. 

이는 /register/add 라는 경로로 요청 들어오면 무조건 registerForm으로 응답하라는 소리이다.

(3) 절약한 코드 

	@GetMapping("/register/add") // 신규회원 가입 화면
	public String register(){
		return "registerForm";
		
	}

이 코드 자체를 안 써도 된다.

3. Redirection

저번 시간에 우리는 회원가입 작성을 잘못 됐는지 검사하고 뭐가 잘못 되었는지 알려주는 함수를 자바스크립트로 jsp 내에 작성하였다. 

이번에는 해당 내용을 controller 안에서 작성해보자. 

일단 검사하는 부분은 나중에 구현하자. 오늘은 무조건 잘못된 기입이라고 가정하고 그 경우 어떤 식으로 처리 해야하는지 확인한다. 

 

잘못 적었으니 어디가 잘못 되었는지 알려주고 재작성 하도록 같은 페이지를 다시 보여주는 게 바람직하다.

// 유효성 검사 -> 무조건 잘못됐어! 

        private boolean isValid(User user) {
			return true;
		}
	// User란 클래스는 요청의 모든 파라미터를 받을 수 있도록 작성되어 있음. 
    // 요청이 들어왔을 때 해당 내용들을 user 객체의 변수 속에 넣어주는 역할은 Spring이 해줌. 
    
    @PostMapping("/register/save")
	public String save(User user, Model m) throws Exception {
		// 1. 유효성 검사 
		if(!isValid(user)) {
			// 이제 배울 내용
            // 잘못되었을 때는 잘못 되었다는 메세지를 띄우고, 
            // 재작성을 위해 다시 똑같은 화면을 보여줘야함.
		}

	}

 

(1) 하는 법 2가지

 a. URL 재작성

    @PostMapping("/register/save")
	public String save(User user, Model m) throws Exception {
		// 1. 유효성 검사 
		if(!isValid(user)) {
        	// 에러 메세지 작성
		String msg = URLEncoder.encode("id를 잘못 입력하셨습니다.", "utf-8");
            
            	//URL 재작성(reWriting)
            	return "redirect:/register/add?msg="+msg; 
            
		}

	}

여기서는 에러 메세지를 작성하고, 해당 메세지를 Get 방식으로 집어넣어 URL 을 재작성한다. 

그럼 이와 같이 나온다.

여기서 String msg 앞에 이상한 명령어들이 잔뜩 붙은 것을 알 수 있다. 왜 그런 것일까?

이유는 다음과 같다. 우리가 Get 방식으로 브라우저에 스트링쿼리를 바로 적을 땐 한글을 값으로 집어넣어도 상관 없었다. 왜냐하면 브라우저에서 자동으로 한글을 브라우저가 알아들을 수 있는 유니코드로 번역해서 듣기 때문이다. 

하지만 위와 같이 우리가 서버에서 직접 쿼리문을 만들어 집어넣을 경우, 브라우저가 스스로 번역기를 돌리지 못하기 때문에 에러가 뜨거나 화면에 한글이 깨져서 나온다.  따라서 밑과 같은 URLEncoder 객체를 써서 브라우저가 알아들을 수 있는 유니코드로 암호화 해줘야 한다.

// URLEncoder 객체를 사용 
// URLEncoder.encode("암호화 시킬 내용","암호화 방식")
String msg = URLEncoder.encode("id를 잘못 입력하셨습니다.", "utf-8");

b. Model 이용 

    @PostMapping("/register/save")
	public String save(User user, Model m) throws Exception {
		// 1. 유효성 검사 
		if(!isValid(user)) {
        	// 에러 메세지 작성
		String msg = URLEncoder.encode("id를 잘못 입력하셨습니다.", "utf-8");
            
            //모델에 에러 메세지를 넣는다? 
			m.addAttribute("msg",msg);
			return "redirect:/register/add";
            
		}

	}

해당 모델 m은 "/register/save"로 매핑된 매소드 내에서만 쓸 수 있는 모델이다. 

따라서 "/register/add"로 돌아가는 현 상황에서는 m에 에러 메세지를 넣어봤자 쓸 수가 없다. 

어짜피 m이 갈 수 없는 영역이기 때문이다. 

 

이 경우 똑똑한 Spring이 모델에 넣은 값을 토대로 자동으로 URL을 재작성 해준다. 

따라서 위의 2코드는 "redirect:/register/add?msg="+msg와 같은 뜻이다.

 

4. 스스로 해보기

@RequestMapping(value = "/register/add", method = {RequestMethod.GET, RequestMethod.POST})
	public String save(User user, Model m){
    
 

//servlet-context에 적는 말
//<view-controller path = "/register/add" view-name = "registerForm"/>



    if(!isValid) {
		
        // 에러 메세지 인코딩
        String msg = URLEncoder.encode("id를 잘못 입력하셨습니다.", "utf-8")
        
        //URL 재작성
        return "redirect:/register/add?msg="+msg;
        
        // 모델 이용하면 Spring이 내가 멍청한 줄 알고 도와줌.
        m.addAttribute("msg",msg)
        return "redirect:/register/add"
        

    }
}