[Spring] 동작 방식 궁금해오...

혜 콩·2024년 3월 28일

Backend

목록 보기
8/9

Spring 공부하면서 노션에 적어놨던 기록인데 노션 들어가서 찾기 어렵고해서 생각날 때마다 보려고 velog로 이사 중 ㅎㅎ.

MVC 패턴

각 컴포넌트를 서로 분리하였기 때문에 각자의 역할에 집중할 수 있어 시스템 결합도를 낮춤

→ 유지보수가 👍🏻, 중복코드 제거 가능, 애플리케이션의 확장성 및 유연성 ⬆️

Model

클라이언트의 요청에 대한 응답을 돌려주는 작업의 결과 데이터

View

웹 브라우저와 같은 애플리케이션의 UI (리소스)

Controller

클라이언트 측의 요청을 직접적으로 전달받는 엔드포인트(EndPoint) 로써 Model 과 View의 중간에서 상호작용을 맡는다. Model에서 받아온 데이터를 View로 전달하는 역할


Spring MVC 동작 구조 🧬

  • Dispatcher Servlet: Front Controller의 역할. Request를 각각의 Controller에게 위임하는 역할
  • HandlerMapping: 요청을 처리하는 각각의 컨트롤러를 탐색 ← java 내 annotation을 통해 탐색
  • HandlerAdapter: 매핑된 컨트롤러의 실행을 요청

컨트롤러를 통해 Model 처리 결과 데이터를 받아오면 HandlerAdapter가 ModelAndView 객체로 변환되며 객체 내에 View name과 View에 대한 정보 데이터가 포함되어있다.

  • ModelAndView: 컨트롤러에 의해 반환된 Model과 View가 Wrapping된 객체
  • View Resolver: View name을 확인하고 컨트롤러로부터 받은 로직 처리 결과를 반영할 View 파일을 탐색
  • View: 처리 결과를 반영한 최종 화면 생성

어노테이션 (Annotation)

@Autowired

@Autowired는 스프링 프레임워크에서 사용되는 어노테이션으로, 객체 간의 의존성을 자동으로 주입

  1. 자동 주입: @Autowired를 사용하면 스프링이 해당 타입의 빈을 찾아 자동으로 필드, 생성자, 메서드 등을 통해 의존성을 주입
  2. 빈 등록: 주입 대상인 클래스나 메서드는 스프링에게 빈으로 등록되어 있어야 한다. 클래스에 @Component나 유사한 어노테이션을 사용하여 스프링에게 빈임을 알릴 수 있음.

Example

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Owner {
    private Dog dog;

    @Autowired
    public Owner(Dog dog) {
        this.dog = dog;
    }

    public String getDogName() {
        return dog.getName();
    }
}

위 예시에서 Owner 클래스는 @Component로 지정되어있던 Dog 타입의 빈을 @Autowired를 통해 자동으로 주입받습니다. 즉, 스프링은 Dog 빈을 찾아서 Owner에 주입합니다.


Form 객체 자동 바인딩

// MemberForm.java

package me.ekmst.hellospring.controller;

public class MemberForm {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
// MemberController.java

...

@PostMapping("/members/new")
    public String create(MemberForm form) {
        Member member = new Member();
        member.setName(form.getName());

        memberService.join(member);

        return "redirect:/";
    }
...
<!-- createMemberForm.html -->
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <form action="/members/new" method="post">
        <div class="form-group">
            <label for="name">이름</label>
            <input type="text" id="name" name="name" placeholder="이름을 입력하세요">
        </div>
        <button type="submit">등록</button>
    </form>
</div> <!-- /container --> 
</body>
</html>

등록 클릭하자마자 form 태그가 실행되어 /members/new 로 form 객체 post

@PostMapping("/members/new") 어노테이션이 걸린 create 메소드 실행

→ Spring MVC는 자동으로 form 데이터를 MemberForm 객체로 데이터 바인딩

form 데이터의 id 속성은 폼 요소를 식별하는 데 사용되기 때문에 폼 데이터를 서버로 전송할 때는 주로 사용되지 않는다. 따라서 name 속성이 서버 전송 시 실제 매개 변수 이름이다.

만약 name=”nameValue” 라면, MemberForm의 필드명도 nameValue로 바뀌어야 Spring에서 식별이 가능해 자동 바인딩이 가능하다.

<form action="/members/new" method="post">
        <div class="form-group">
            <label for="name">이름</label>
            <input type="text" id="name" name="nameValue" placeholder="이름을 입력하세요">
        </div>
        <button type="submit">등록</button>
    </form>
// MemberForm.java

public class MemberForm {
    private String nameValue; // name 속성을 기준으로 필드명을 "nameValue"로 유지

    public String getNameValue() {
        return nameValue;
    }

    public void setNameValue(String nameValue) {
        this.nameValue = nameValue;
    }
}

Model 객체

  • Controller의 메서드는 Model이라는 타입의 객체를 파라미터로 받을 수 있다.
  • JSP Servlet을 사용할 때는 request 내장 객체에 정보를 담아 넘겨주었지만, Spring에서는 Model를 사용해 View로 데이터 전달
@GetMapping("/members")
    public String list(Model model) {
        List<Member> members = memberService.findMembers();
        model.addAttribute("members", members);
        return "members/memberList";
    }

key=“members”, value=members 데이터를 model이라는 객체에 저장하여 members/memberList 뷰로 데이터 전송

혹은 @ModelAttribute(속성 이름)를 사용하여 데이터를 전송할 수도 있다.

@ModelAttribute("myname") int name

RedirectAttributes

  • 리다이렉션을 수행할 때 한 컨트롤러에서 다른 컨트롤러로 속성(Attributes)을 전달하는 역할을 하는 스프링 프레임워크의 인터페이스

addFlashAttribute()

(key, value) 형태의 파라미터를 이용하여 화면에 단 한번만 사용하기 때문에 새로고침하면 data가 사라짐

→ 검증 결과, 성공 실패 여부 메세지와 같이 임시 데이터를 다루기에 적합하다.

→ 세션에 저장하고 주소 창에 표기되지 않기 때문에 폐쇄적

addAttribute()

리다이렉트 할 주소 뒤에 쿼리스트링 형태로 데이터 전송

@Controller
public class MyController {
    @PostMapping("/submitForm")
    public String submitForm(@ModelAttribute("formData") FormData formData,
                             RedirectAttributes redirectAttributes) {
        
				...

        // Add attributes to redirectAttributes
        redirectAttributes.addAttribute("orderNumber", "1010233");
        redirectAttributes.addFlashAttribute("message", "Order completed successfully.");

        // Redirect to another page
        return "redirect:/success";
    }

// 출처: https://jake-seo-dev.tistory.com/484

profile
배우고 싶은게 많은 개발자📚

0개의 댓글