Web/Spring

[Spring] Ch02.Spring MVC (9) 관심사의 분리와 MVC 패턴 이론 ~ (12) 관심사의 분리와 MVC 패턴 - 원리②

OptimizerStart 2025. 6. 1. 15:20

[Spring] Ch02.Spring MVC (9) 관심사의 분리와 MVC 패턴 이론 ~ (12) 관심사의 분리와 MVC 패턴 - 원리②

관심사의 분리, MVC 패턴 -이론

Spring MVC

  • MVC 패턴 중 하나
  • MVC 분리 중 하나임

SOLID ⭕ 암기. 면접

  • OOP 5대 설계 원칙 - 3개가 분리, 1개 다형성

S 단일 책임 원칙

  • 1 책임(= 관심사) : 1 메서드
  • SRP Single Responsibity Principle
  • 단일 책임 원칙에 의해 ✅을 쪼개 놓은 것

O OCP - Open & Close Principle

  • 상속 OK, 변경 X - 템플릿을 상속해서 완성하는 건 좋은데 템플릿 변경하지마.
  • 템플릿은 여러 사람들이 쓰는 공통적인 것이기 때문

L 다형성 (추후 정리)

I

D

 

설계

  1. 그룹화 (= 분리 )
  2. (그룹 간)관계 맺어주기 ( 구조화 ) = 시스템, SW 구조화
    • 통으로 두는 것, 쪼개는 것 등 → 변경에 유리한 구조가 좋음

Solid 원칙

분리 대상 - 3 ⭕ 암기

코드를 분리하는 기준

  1. 관심사 (= 일의 분리)
    • 관심 Concern 걱정거리, 문제, 할 일(해야할 일) Work, 작업 , 풀어야할 문제
    • 목적이 다른 코드를 섞지마
    • Seperation of Concern SOC
  2. 변하는 것 & (자주) 변하지 않는 것 (Template)
    • Solid의 OCP - Open(허가) & Close Principle 상속OK, 변경 X
    • Template(상속으로 바뀌는 것 완성), Strategy (매개변수 주입) 패턴
    • Common & UnCommon Code
  3. 중복 코드 - 공통 코드로 분리

그룹화와 분리가 중요

 

서블릿 작은 서버 프로그램

= 메서드 요청 들어오면 받아서 처리 후 응답함

서블릿의 처리 흐름

 

 

View 출력의 분리, 출처: 남궁성_Spring의 정석 교안

관심사의 분리

  1. 공통 코드의 분리 - 입력의 분리 request.getParameter()
    1. 각 컨트롤러의 입력 부분을 제거 후 단독 입력을 앞에 위치
    2. 메서드 선언부
    • 객체 배열 요소 각각 매개변수로 받기
    • 자동 형변환
  2. 변하는 것과 변하지 않는 것의 분리 - 출력(view)의 분리
    1. Model 객체 필요 - 결과 출력용 값 저장
      • [기존] 같은 메서드 내에 있어서 처리한 값을 출력이 가능했음
    2. 출력 코드
      • HTML 응답은 자주 변해서 분리 필수
    ex. 은행 거래내역 조회 1년 - pdf, csv, excel 파일 중 선택한 형식 보여주기

전처리

  • 입력을 공통 처리하자

DispatherServlet

  1. 입력 & 변환 (자동)창구 역할, 공통 처리 후 전달
  2. 요청을 받아서 뿌려줌
  3. 모델 객체 생성 - 결과 저장소
    • controller에 전달

약속, 틀

  • main() { 코드 }
  • 스레드 run () { 코드 }
  • 서블릿 service() { 코드 }

=> 하는 일을 똑같음 . 메서드 명만 다름

 

Web 서비스 요청

  • 파일(리소스 집합) 요청.
  • url ‘경로/파일이름’

 

MVC 패턴

  • Controller 처리
  • Model 결과 저장소.
    • 정의 : 분리된(코드 위치가 다른) Controller와 View간의 데이터를 주고 받을 수 있게 하는 객체
    • 자료구조 : Map (Key, Value)Key Value 
      “year” 2025
      “month” 5
      “day” 25
      “yoil” “금”
    • 단점 : 쪼갬으로서 성능은 떨어짐
    • 장점: 유지보수성 ↑
model.addAttribute("name", "Hello");

 

  • 원리
    • 컨트롤러가 return 뷰; 하면 request.setAttribute(”myDate”, myDate)로 내용(속성) 복사 후 jsp로 요청 객체를 넘김.
    ${myDate.year} =/= myDate가 참조하는 실제 인스턴스 접근 X
    1. request.getAttribute("myDate") → 같은 객체 참조 획득
    2. Introspector 로 getter호출
    3. 반환값(2025)을 문자열로 렌더링
  • model.addAttribute(”myDate”, myDate);
  • 주의 사항

model.addAttribute()를 생략하면 Spring은 타입 이름을 decapitalize한 값을 모델 키로 자동 등록

// 4단계. 메서드의 매개변수를 변경. int -> MyDate
@Controller // 1. 원격 프로그램 등록
public class YoilTellerS4 {
	
	@RequestMapping("/yoilpracs4") //2. URL과 메서드 연결 (서블릿)
	public String getYoil(MyDate2 myDate2, Model model) { // TODO  MyDate2 myDate 가 안되는 이유
		
		// .. 생략 .. 
		// TODO 왜 year, month, day가 출력이 안되나?  
		model.addAttribute("myDate", myDate2);
		//model.addAttribute("myDate2", myDate2);// 위에 처럼 명시적으로 작성하지 않으면 톰캣이 자동으로 등록할 떄 myDate2로 씀
		return "yoilprac"; // WEB-INF/views/yoilprac.jsp
		
		// .. 생략 .. 
	}
	// .. 생략 .. 

}
  • View 출력
    • 결과 보여줌
    • 경로와 확장자는 항상 동일해서 view 이름(바뀌는 부분)만 적게함.
    • return "yoil"; // WEB-INF/views/yoil.jsp
    • 에러 페이지 - 유효성 검사
    🟢튜닝. gpt가 쪼갠 코드를 붙임(같은 스코프)으로써 성능을 올릴 수 있음

 

Spring MVC 구조

Spring MVC 원리, 출처: 남궁성 Spring 정석 교안

  1. 요청이 들어오면 DispatcherServlet이 요청을 받음
  2. DS가 Controller에게 요청내용을 전달
  3. Controller가 요청 내용 기반 처리 후 결과를 Model에 저장, 작업 결과 보여줄 View 지정
    1. 반환타입 String 뷰이름 반환
    2. 반환타입 void 매핑된 url의 끝단어가 뷰 이름 (잘 안씀)
      view 를 반환하지 않을 때 url과 동일한 jsp인 view를 보여줌
      3. 반환타입 ModelAndView Controller가 model 만들고 사용 가능 (잘 안씀)
      • 메서드의 매개변수로 model을 받지 않고 메서드 구현부에 model 만듦
      • addObject(”속성명”, 값);
      • view 이름 지정 mv.setViewName("yoil");
      • 반환 return mv; 객체
  4. DS가 작업 결과가 저장된 Model 객체를 View에 전달
  5. View가 응답(파일)을 만들어 클라이언트에게 전송

 

 

프레임워크

프로그래밍 형식

편리한 코딩 방식 제공

 

메서드 별도로 만들기

코드 드래그 우클릭 > Refactor > Extract Method

메서드 별도로 만들기 STS 환경

 

컴파일러에게 매개변수 이름은 중요하지 않음. 타입 중요 O

  • arg0, arg1 이름을 저장안하기 때문.
java.lang.String getYoil(javax.servlet.http.HttpServletRequest arg0, org.springframework.ui.Model arg1)
char getYoil(com.fastcampus.ch2.MyDate arg0)

 

 

매개변수 이름 얻는 법 -2

  1. Reflection API
    • -parameters 옵션 주고 컴파일 해야함
    • jdk 1.8 이후만 가능
  2. Class 파일 직접 읽기
    • 1번 실패시 2번 이용
    • jdk 1.8 이전

 

javac -parameters 옵션

매개변수 이름 저장

jdk1.8부터

compiler 옵션

컴파일러 jdk가 21버전이어도 자바 프로젝트 버전이 1.6 (1.8 미만)일 경우 매개변수 이름이 제대로 뜨지 않음.

  • pom.xml 파일 수정
    • <properties> <java-version> 11 </java-version>
    • maven > plugin > source >${java-version} 으로 작성

pom.xml 수정 후 매개변수 이름 출력 확인

 

<properties>

  • pom.xml 위치함
  • 파일에서 사용될 값을 <propterties> 태그 안에 정의, 아래에서 참조할 수 있도록함.
  • 수정 시 pom.xml maven update 필수

pom.xml

 

 

navigator

소스 파일, 클래스 파일(target폴더) 볼 수 있음

 

Controller에서 view 이름만 반환하는 이유

원래 View이름과 Model 리턴해야함 Model을 생성해서 받아서 View이름만 리턴

이유 : 참조형 매개변수로 이미 객체 주소를 알고있기 때문

  • DS에서 model객체를 생성해서 controller에게 제공했기 때문. 즉 map 객체 주소를 이미 알고있기 떄문.

 

 

reflection api

reflection

실행 중인 프로그램이 자기 자신(클래스, 메서드, 필드 등)의 구조를 메타정보로 조회 및 조작할 수 있는 기법

  • 새로운 인스턴스 생성, 메서드 호출, 필드 값 읽기/쓰기, 애너테이션 정보 확인

사용법

  • class 객체를 얻음 -3 방법

톰캣이 사용자가 URL에 입력한 값을 자동으로 객체로 생성하는 원리

  • map 형태로 입력값(String)을 저장해 놨다가
  • 사용자 값과 메서드의 메타 데이터를 이용해 Object [] 타입 객체 배열을 동적으로 크기에 맞게 생성
    • key가 존재하지 않으면 null을 Object[] 에 저장(반환)

[참고 코드] https://github.com/castello/spring_basic/blob/main/ch2/MethodCall3.java ⭕중요 🟥 실습

  • Spring 메서드 매개변수에 맞게 값을 넣어주고 변환하는지 알려주는 예제

 

1. 하드코딩 된 메서드 매개변수

String viewName = obj.main(2021, 10, 1, model); // 아래 줄과 동일. 매개변수 목록이 메서드마다 다르기 때문에 가변인자 사용
String viewName = (String)main.invoke(obj, new Object[] { 2021, 10, 1, model });  // reflection api 이용한 호출

 

2. 넘겨 준 값으로 동적으로 객체 배열 만듦

Object[] argArr = new Object[main.getParameterCount()];

 

 

 

 

톰캣이 Model 인스턴스를 자동으로 생성하는 원리

model 인터페이스를 구현한 클래스의 객체가 존재하지 않을 때. model의 구현체를 생성함

// paramType중에 Model이 있으면, 생성 & 저장 
			if(paramType==Model.class) {
				argArr[i] = model = new BindingAwareModelMap(); 
			} else if(value != null) {  // map에 paramName이 있으면,
				// value와 parameter의 타입을 비교해서, 다르면 변환해서 저장  
				argArr[i] = convertTo(value, paramType);				// 자동변환 String -> int 
			}

코드 참고

ch2/MethodCall3.javacastello/spring_basic

 

spring_basic/ch2/MethodCall3.java at main · castello/spring_basic

남궁성의 스프링 기본 강의 @fastcampus.co.kr. Contribute to castello/spring_basic development by creating an account on GitHub.

github.com

 

 

[ 추가 실습 ] 매개변수가 객체일 때 값과 연결해주는 작업

https://github.com/castello/spring_basic/blob/main/ch2/SetterCall.java

 

spring_basic/ch2/SetterCall.java at main · castello/spring_basic

남궁성의 스프링 기본 강의 @fastcampus.co.kr. Contribute to castello/spring_basic development by creating an account on GitHub.

github.com

 

 

@WebServlet

Spring @Controller + @RequestMapping 합친 것

 

cf. Spring vs Servlet

  • Spring 클래스 앞에 @Controller 붙임. 메서드 앞 @RequestMapping으로 연결
  • Servlet 클래스 단위 매핑(연결) O. 메서드 단위 연결 X
    • 특징
      • HttpServlet 상속 받음.
      • service() 사용 (오버라이딩)
      • 메서드 매개변수 HttpServletRequest, HttpServletResponse 2개 필요
    • 단점: Spring에 비해 클래스를 많이 만들어야 함.

 

사용자 입력값의 Value의 타입은 Stirng[] 배열임