언어 및 도구들 공부/Spring

Spring MVC 패턴에서 컨트롤러 메서드와 view의 데이터 주고받기

Dr.Mlem 2024. 11. 12. 21:44
Q1.
스프링을 이용한 mvc 패턴의 프로젝트에서, 어떤 컨트롤러의 특정 메서드롤 통해서 생성된 값을 담고 있는 모델 객체는, 해당 메서드가 연결된 view에서만 사용할 수 있는 것인가? 다른 컨트롤러에서 쓰거나, 같은 컨트롤러 내의 다른 메서드가 그냥 쓸 수는 없는가?
 
 
 

A1.

스프링 MVC에서 특정 컨트롤러 메서드가 생성한 모델 객체는 기본적으로 해당 메서드가 반환하는 view에서만 사용할 수 있습니다. 이 모델 객체는 컨트롤러 메서드와 view 사이에서 전달되는 일시적인 데이터로, 요청/응답 사이에서만 유효하게 사용됩니다.

다시 말해, 한 메서드에서 설정한 모델 객체는 기본적으로 다른 컨트롤러 메서드나 같은 컨트롤러 내의 다른 메서드에서 바로 사용할 수 없습니다. 스프링은 요청이 끝나면 모델에 담긴 데이터도 같이 사라지기 때문입니다.

다른 컨트롤러 메서드나 다른 요청에서도 모델 데이터를 재사용하려면?

  1. RedirectAttributes 사용
    만약 다른 요청으로 리다이렉트하면서 모델 데이터를 넘기고 싶다면, RedirectAttributes를 사용할 수 있습니다. 이렇게 하면 리다이렉트된 요청에서도 데이터를 사용할 수 있습니다.addFlashAttribute는 데이터를 세션에 잠시 저장하여 리다이렉트 후에도 해당 데이터를 사용할 수 있게 해줍니다.
     
     
    @GetMapping("/first")
    public String firstMethod(RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("key", "value");
        return "redirect:/second";
    }

    @GetMapping("/second")
    public String secondMethod(Model model) {
        // 모델에 "key"가 포함되어 사용 가능
        return "secondView";
    }
  2. Session Attributes 사용
    세션에 저장하여 여러 요청에서 접근 가능하게 하려면, @SessionAttributes를 사용할 수 있습니다. 이 방법은 사용자가 브라우저를 닫기 전까지 데이터를 유지할 수 있게 해줍니다.
    @Controller
    @SessionAttributes("sessionData")
    public class MyController {

        @GetMapping("/store")
        public String storeInSession(Model model) {
            model.addAttribute("sessionData", "This data is in session");
            return "storeView";
        }

        @GetMapping("/retrieve")
        public String retrieveFromSession(Model model) {
            // 세션에 저장된 "sessionData" 사용 가능
            return "retrieveView";
        }
    }
  3. ModelAndView 사용
    ModelAndView를 통해 데이터와 view를 함께 설정하여 명확하게 전달할 수도 있습니다. 이 방법은 컨트롤러에서 모델과 뷰를 동시에 관리하는 방법입니다.
  4. 데이터베이스나 다른 지속성 저장소 활용
    만약 데이터가 요청 간에 계속해서 필요하다면, 데이터베이스나 캐시 같은 외부 저장소를 활용하는 것도 방법입니다. 이렇게 하면 여러 요청에서 데이터를 지속적으로 사용할 수 있습니다.

요약

  • 기본적으로 한 메서드에서 생성한 모델 데이터는 해당 요청과 응답 사이에서만 유효하며, 다른 메서드에서 바로 접근할 수 없습니다.
  • 리다이렉트로 데이터를 전달하려면 RedirectAttributes를, 세션에서 데이터를 공유하려면 @SessionAttributes를 사용합니다.
  • 데이터가 여러 요청에 걸쳐 필요하다면 데이터베이스 등 외부 저장소를 고려하는 것이 좋습니다.

 

 

 

Q2.

쿼리 스트링이나 패스파라미터를 이용하는 것도 하나의 방법일까?

 

 

 

A2.

네, 맞습니다! 쿼리 스트링이나 패스 파라미터를 활용하는 것도 다른 요청 간에 데이터를 전달하는 효과적인 방법입니다. 이러한 방법은 주로 간단한 데이터나 식별자를 전달할 때 유용하게 사용됩니다.

1. 쿼리 스트링 (Query String)

쿼리 스트링은 URL 뒤에 ?key=value 형식으로 데이터를 전달하는 방식입니다. 여러 개의 데이터를 전달할 때는 &로 구분할 수 있습니다. 다음은 쿼리 스트링을 이용한 예시입니다:

 

@GetMapping("/first")
public String firstMethod() {
    // 필요한 데이터를 쿼리 스트링으로 전달
    return "redirect:/second?key=value";
}

@GetMapping("/second")
public String secondMethod(@RequestParam("key") String key) {
    // key 값이 "value"로 전달되어 사용 가능
    System.out.println("Received key: " + key);
    return "secondView";
}
 

위 예제에서는 firstMethod에서 secondMethod로 리다이렉트할 때 key=value 형태의 쿼리 스트링으로 데이터를 전달하고, secondMethod에서는 @RequestParam을 통해 해당 데이터를 받을 수 있습니다.

2. 패스 파라미터 (Path Variable)

패스 파라미터는 URL 경로의 일부로 데이터를 전달하는 방식입니다. 보통 특정 리소스를 식별하는 ID나 주요 데이터를 전달할 때 사용됩니다. 예를 들어, /user/{userId}와 같은 방식으로 데이터를 전달할 수 있습니다.

 

 

@GetMapping("/user/{userId}")
public String getUserProfile(@PathVariable("userId") Long userId, Model model) {
    // userId로 사용자 데이터를 조회 후 모델에 추가
    model.addAttribute("userId", userId);
    return "userProfileView";
}


위 코드에서는 getUserProfile 메서드가 호출될 때 userId 값을 경로에서 받아 사용할 수 있습니다. 예를 들어 /user/123 URL로 요청을 보내면, userId 파라미터는 123으로 매핑됩니다.

쿼리 스트링 vs 패스 파라미터

  • 쿼리 스트링은 보통 선택적 데이터나 부가적인 정보를 전달할 때 많이 사용됩니다. 예를 들어, 정렬 기준, 필터 조건 등 추가적인 정보가 필요할 때 주로 사용됩니다.
  • 패스 파라미터는 주로 리소스를 고유하게 식별하는 데 사용되며, 특정 리소스를 지정해야 하는 경우에 적합합니다. 예를 들어, 사용자 ID, 게시물 ID 등을 전달할 때 자주 사용됩니다.

장단점 요약

방법장점단점
쿼리 스트링 여러 값을 쉽게 전달할 수 있음 URL 길이가 길어질 수 있음
패스 파라미터 리소스를 명확하게 식별 가능 데이터가 경로에 포함되어 보안상 주의 필요

쿼리 스트링이나 패스 파라미터 모두 간단한 데이터나 고유 식별자를 전달할 때 유용한 방법이므로, 상황에 맞게 사용하면 좋습니다.

 

 

 

 

Q3.

컨트롤러의 특정 메서드에 연결된 뷰에서만 서로 모델 객체로 데이터를 주고 받을 수 있는 것인가? 그냥 메소드에서 뷰쪽으로의 일방적인 전송만 가능한가?

 

 

 

A3.

스프링 MVC의 기본 구조에서는 컨트롤러의 특정 메서드에서 뷰로의 일방향 데이터 전송만 가능합니다. 즉, 컨트롤러 메서드에서 설정한 모델 객체는 해당 요청에 응답할 때 뷰로 전달되지만, 뷰에서 컨트롤러로 직접적으로 데이터를 되돌려 보내는 것은 불가능합니다.

뷰에서 컨트롤러로 데이터를 전송하려면?

뷰에서 컨트롤러로 데이터를 다시 보내고 싶다면, 폼 데이터 제출 방식을 사용해야 합니다. 즉, 사용자가 뷰에서 입력한 데이터를 다시 컨트롤러로 전달할 때는 다음과 같은 방법들이 있습니다.

1. 폼 데이터 (Form Data) 사용

HTML 폼을 통해 데이터를 입력한 후 제출하면, 해당 데이터가 새로운 요청으로 컨트롤러에 전달됩니다. 이 방식은 뷰와 컨트롤러 간의 양방향 데이터 전송을 가능하게 합니다.

예를 들어, 사용자가 뷰에서 폼을 제출하면 @RequestParam 또는 @ModelAttribute를 사용하여 데이터를 받을 수 있습니다.

 

 

@GetMapping("/form")
public String showForm(Model model) {
    model.addAttribute("formData", new FormData());
    return "formView";
}

@PostMapping("/submitForm")
public String handleFormSubmission(@ModelAttribute("formData") FormData formData) {
    // 폼 데이터 처리
    System.out.println("Received data: " + formData);
    return "resultView";
}

 

위 코드에서 showForm 메서드는 폼을 보여주는 뷰를 반환하며, 사용자가 입력한 데이터를 submitForm 메서드가 처리하는 구조입니다.

2. AJAX (비동기 통신)

JavaScript를 사용해 AJAX 요청을 보내는 방식으로도 뷰에서 컨트롤러로 데이터를 전송할 수 있습니다. 이 방법은 페이지를 새로 고침하지 않고 데이터를 전송할 수 있게 해줍니다.

 

// JavaScript 예제
fetch('/submit', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ key: 'value' })
}).then(response => response.json())
  .then(data => console.log(data));

 

컨트롤러에서는 @RequestBody를 사용하여 AJAX로 전송된 데이터를 받을 수 있습니다.

 
@PostMapping("/submit")
@ResponseBody
public ResponseData handleAjaxRequest(@RequestBody RequestData requestData) {
    // AJAX 데이터 처리
    return new ResponseData("success");
}
 

정리하자면

  • 스프링 MVC에서는 컨트롤러 메서드에서 뷰로 데이터가 일방향으로 전송됩니다. 뷰에서는 직접적으로 모델 객체를 수정하거나 컨트롤러로 다시 전달할 수 없습니다.
  • 뷰에서 컨트롤러로 데이터를 보내려면 폼 제출이나 AJAX 요청을 사용해야 합니다.
  • 양방향 데이터 전송이 필요한 경우, 폼 데이터 또는 AJAX와 같은 방법을 활용하면 뷰와 컨트롤러 간 데이터를 주고받을 수 있습니다.