본문 바로가기

Spring

spring MVC가 뭔데여(근데 이제 spring framework 특징을 곁들인)

[출처] - [Spring] Spring에서 말하는 Spring MVC 이란? · linked2ev

 

(혹시 사진 문제가 되면 말해주세요 지울게요) 

 

냅다 spring MVC 처리 순서

spring을 한번 만져봤으면 대강은 이해할 수 있을 거 같다.

 

물론.. 잘 모르겠긴 한데 그래도 대충 흐름은 알겠달까..?

 

1. 클라이언트가 URL로 접근한다. 

2. DispatcherServlet가 Request(요청)을 HandlerMapping에게 위임한다.

3. HandlerMapping가 Mapping 된 Controller에게 위임한다.

4. Controller에서 들어온 요청을 처리하고 결과 데이터를 담아 View를 DispatcherServlet에 전달한다.

5. DispatcherServlet는 전달받은 View 정보를 ViewResolver에게 전달한다.

6. ViewResolver는 model에 담겨온 데이터?를 rendering 하고 view의 논리 이름을 물리 이름으로 바꾼다.

7. View 인스턴스를 다시 DispatcherServlet에 넘긴다.

8. 그렇게 출력된 최종결과를 우리가 보는 것이다..!

 

간단한 흐름이 이렇고 세세하게 들어가면............. 많겠찌..?

 

쪼끔만 더 세세하게 들어가 보자. 음.. 뭐부터 알아봐야 할까.. 막막하군


 

  • InternalResourceViewResolver 

JSP의 경우 InternalResourceViewResolver 가 자동으로 등록되고, 사용된다고 한다. 

이 녀석은 WAR 파일 내 포함된 뷰 템플릿을 찾는다고 한다. 아까 view의 논리 이름을 물리 이름으로 바꾼다고 했는데, 아마 그런 역할이 아닐까..? 싶다.. (아닌가..) 

sevlet-context.xml

 

xml에 이렇게 빈으로 등록해 두면 컨트롤러에서 뷰를 반환할 때 자동으로 앞, 뒤에 붙여준다!

컨트롤러 예시

 

. 이렇게 있으면 자동으로 /WEB-INF/view/loginForm.jsp를 찾아서 보여준다는 것이다! (/WEB-INF/view 경로에 있는)

 

  • Spring IoC (Inversion of Control) Container

빈이 뭔지 알기전에 spring IoC Container 를 알아야 한다. 이게 뭐냐면 객체의 생성, 생명주기를 책임지고 객체 간의 의존성을 관리해 주는 스프링 컨테이너이다. 왜? 객체의 의존성을 역전시켜 객체 간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 해 준다. 

 

  • DI (Dependency Injection) 

DI라는 개념도 나온다. 이건 뭐냐면 클래스의 인스턴스를 직접 생성하지 않고 spring container로부터 생성된 bean을 주입받는 것이다. 알겠지만 모르겠다. 

예제를 보자. 일단 클래스의 인스턴스를 직접 생성하는 경우다.

public class TestService {
	private TestDao testDao;
    
    public TestService(){
    	this.testDao = new TestDao(); // 직접 생성
    }
}

 

그럼 이제 의존성을 주입해 보겠다.

@Service
public class TestService {

	@Autowired
	private TestDao testDao;
   
}

 

간단하게 TestDao도 @Repository로 빈으로 등록돼 있을 거고, TestService에서 @Autowired으로 의존성을 주입받아서 사용한다.( Annotation에 대해선 따로 정리하겠다. ) 이런 방식의 의존 주입을 필드 주입이라고 한다. 

 

정리하면서 알아낸 사실인데 이때까지 나는 필드 주입으로 다 해왔으나 이 방법은 권장되는 방법은 아니란다. 주입한 것을 중간에 바꿀 수 없기도 하고(변경하는 경우가 많지는 않다고 한다.) 변수를 private로 선언하기 때문에 이후 외부에서 접근이 불가능하기 때문이란다. 

@Service
public class TestService {
	private TestDao testDao;
    
    @Autowired
    public void TestService(TestDao testDao){
    	this.testDao = testDao;
    }
}

 

이렇게 하는 방식이 생성자 주입 방식인데 이게 권장되는 방식이라고 한다. 이 방식으로 주입하면 처음 애플리케이션이 조립되는 시점(스프링 컨테이너에 올라가는)에 주입이 된다고 한다.

 

  • beans 

그럼 이제 빈으로 등록한다 했는데 빈이 뭐냐.

bean은 위에서 설명했던 spring 컨테이너가 관리하는 '객체' 이다. spring이 객체가 있다는 걸 어떻게 아냐? 

그게 아까 예시에서도 보였던 @Service @Autowired 등의 어노테이션이 붙은 클래스를 자동으로 인지한다. 한 가지 더 있긴 하다. Bean Configuration File에 직접 Bean을 등록하면 Spring이 인지할 수 있다. 

 

근데 spring 컨테이너가 빈을 찾아야 하잖아? 어노테이션이 붙은 객체들을 여기서 찾아. 라고 지정하는 게 component-scan이다.

servlet-context.xml

 

이런 식으로 servlet-context.xml에 지정해 놓으면 base-package로 지정해 놓은 패키지에서 어노테이션이 붙은 빈들을 찾아서 spring 컨테이너가 관리하게 된다.

 

정리하다 보니 spring framework 특징도 같이 정리해야겠다. 특징은 POJO / IoC / DI / AOP 크게 이렇게 있다. 2개는 위에서 설명했으니 나머지 2개를 설명해 보겠다. 

 

  • POJO(Plan Old Java Object)

안녕 포조? 포조가 뭐냐 순수 자바 객체란다. spring에서 객체들은 포조를 따른다? 간단하게 기본적인 형태의 Java 객체이다.! 는 이렇게 설명하면 안 된다. 나 같은 바보들은 아주아주 풀어서 설명해야 한다.. 그래서 아주아주 기본적인 형태의 객체가 뭔데? 

public class test{
	private String id;
    private String pw;
    
    public String getId(){
    	return id;
    }
    public String setId(String id){
    	this.id = id;
    }
    public String getPw(){
    	return pw;
    }
    public String setPw(String pw){
    	this.pw = pw;
    }
}

 

그렇다. 별거 없고 근야 getter와 setter로 구성된 단순한 객체 형태를 말한다. 

 

  • AOP(Asept-Oriented Programming)

마지막! 관점 지향 프로그래밍이다. 정처기 공부할 때 다 했던 건데 역시 다 까먹었고요..^^ AOP는 핵심 기능에서 부가적인 기능을 분리했다.라고 한다. 내가 이해한 건 공통되는 코드를 모듈화로 분리해서 재사용에 용이하다..? (아닐수도 있다.. 아직 잘 모르겠다 AOP는)

 


 

controller에서 view로 데이터를 넘길 때, 넘기는 방법에 대해 알아보겠다.

 

  • Model
@GetMapping("/login")
public String login(Model model){
	String id = "id";
	model.addAttribute("id",id);
    
    return "login";
}

 

Model은 key-value 쌍으로 이루어져 있다. id라는 key에 id라는 String의 값을 담아서 login.jsp(view)에 데이터를 보낼 수 있다. 그럼 jsp에선 ${id}로 value를 사용할 수 있다! 참고로 String 형태로 반환한다.

 

  • ModelAndView

Model과 비슷하게 생겨서 초반에 날 헷갈리게 했다. 똑같은 건 줄. 근데 지금 보니까 모델과 뷰라고 아주 대놓고 써놨네.. 

@GetMapping("/login")
public String login(){
	ModelAndView mav = new ModelAndView();
    mav.addObject("id",id);
    mav.setViewName("login");
    
    return mav;
}

 

사용법은 이렇고 model과 별반 다르지 않다. 그냥 view도 포함해서 객체로 반환하는 거? 요즘은 잘 안 쓴다고 한다.

 

  • RedirectAttributes

컨트롤러를 작성하다 보면 redirect가 필요할 때가 있다. 근데 문제는 redirect는 지정된 주소로 새로운 GET 요청이 시작되기 때문에 이전에 모델에 저장된 데이터는 없어진다. 무슨 말이냐? 

 

@GetMapping("/login")
public String login(Model model){
	String id = "id";
	model.addAttribute("id",id);
    
    return "redirect:/login";
}

 

이렇게 하면 login이라는 url로 재요청이 가는데 model에 담아 보냈던 id? 없어진다. 쓸 수 없다는 거다. GET 방식이면 URL에 지정해 줘도 되겠지만.. 역시나 보안이 문제다. 근데 전달할 방법은 다 있다. 이럴 때 쓰는 게 RedirectAttributes다. 일단 사용 방법을 먼저 보겠다.

 

@GetMapping("/login")
public String login(RedirectAttributes redirectAttributes){
	String id = "id";
	redirectAttributes.addFlashAttribute("id",id);
    
    return "redirect:/login";
}

 

보면은 addFlashAttribute로 추가한다. 그렇다. 플래시 속성으로 추가된 데이터는 재요청되기 전에 세션에 임시로 저장된다. 재요청이 이루어진 후 세션에 저장돼있던 플래시 속성이 URL을 제공하는 컨트롤러의 Model 객체에 자동으로 추가된다. 근데 한 번만. 이후에 제거된다. 

 

간단하게 알아봤다... DispatcherServlet은 따로 정리해 보고..(언제 할지 모르겠다 따로 한다는 게 한 바가지다.) HandlerMapping도.... ........ 차근차근 추가할 게 있으면 추가하겠다...


참고 출처

[Spring] Spring에서 말하는 Spring MVC 이란? · linked2ev
 

[Spring] Spring에서 말하는 Spring MVC 이란?

넘어가기 위해 정리하고 가자. 스프링에서 말하는 Spring MVC란?

linked2ev.github.io

[Spring] 의존성 주입 (Dependency Injection, DI) 예제 — Mimah (tistory.com)
 

[Spring] 의존성 주입 (Dependency Injection, DI) 예제

의존성 주입 (Dependency Injection, DI) MVC 모델을 사용하여 개발한다고 가정할 때 Controller에서는 Service에 있는 메서드를 호출해야 하고, Service에서는 Repository(or DAO,...)에 있는 메서드를 호출해야 한다.

mimah.tistory.com

 

'Spring' 카테고리의 다른 글

HTTP 특징  (0) 2024.06.13
Spring 이론 - 클라이언트와 서버 Tomcat / Servlet / JSP  (0) 2024.06.06
spring Annotation 모음  (0) 2024.05.22