새로운 내용을 공부할 때
새로운 내용의 공부를 시작할 때 용어의 정의를 이해하지 못하거나 정확하게 알지 못한다면 그 용어가 포함된 문장을 이해하지 못합니다.
작은 단어 하나가 내용을 이해하지 못하게 하기 때문에 용어를 정확하게 이해하는 것이 중요합니다.
스프링과 MVC 학습
📌 스프링과 MVC
1. 오늘의 학습 주제
- 스프링 MVC는 왜 필요할까
- 구조와 동작 방식을 알아보자
- 설계와 응용을 해보기(“언제 적용하고, 언제 피할 것인가?”)
- 내 것으로 만들기
MVC가 왜 필요한가?
MVC 패턴의 목적
-
관심사의 분리(SoC, Separation of Concerns)
Model : 데이터 및 비즈니스 로직 관리
View : 사용자에게 보여지는 화면 (UI)
Controller : 사용자의 요청을 처리하고 Model과 View를 연결
-
유지보수성이 높아진다.
- 코드 중복 감소한다.
- 버그 수정하기 편하다.
- 확장하기 편하다
- 단위 테스트 및 테스트가 편하다
- 가독성이 높아진다
관심사를 분리하게 되면 공통 로직이 한 곳에 모여 있어 재사용하기가 편합니다. 클라이언트의 요구사항으로 변경이 필요한 부분은 한꺼번에 생기지 않고 집중된 화면이나 비즈니스 로직, 데이터 구조 변경이 별도로 오게 됩니다. 그리고 확장을 하기 위해 코드를 추가해도 서로 분리되어 영향 범위가 작아집니다. 작아진 범위로 테스트하기도 편하고 코드 라인이 줄고 어떤 역할을 하는지 알기에 가독성이 높아집니다.
하나의 메서드 내에 여러 관심사가 있는 경우 데이터 조회를 한번한 결과로 공유하여 사용할 수 있습니다.
빠른 개발이 가능하고 코드가 짧다면 가독성도 나쁘지 않고 코딩이 가능해집니다.
요구사항이 추가되면서 코드가 길어지게 되면 처음 조회한 결과가 불변 객체가 아니라면 조회 이후부터 모드 로직을 봐야합니다.
해당 데이터의 속성이 중간에 변경이 되었는지, 조회된 결과가 신뢰할 수 있는 데이터인지 알 수가 없습니다.
그리고 테스트를 위해서 필요한 준비물도 너무 많아지는 걸 느꼈습니다.
회원삭제시 회원 고유번호와 사유가 필요하다고 할때 메서드 내에 탈퇴불가 관심사가 포함되어 있다면
탈퇴불가에 필요한 필드 값도 알고 있어야합니다.
이게 누적이 되다보니 테스트하기가 어려워지고 점점 통합테스트나 UI와 같이 하는 테스트로 변경이 됩니다.
Spring MVC의 사용의 의미
문제 인지
사용자 관점 : 브라우저나 모바일 앱에서 요청을 보냈을 때 자신에게 필요한 정확한 응답을 받고싶다.
개발자 관점 : 클라이언트의 요청을 받아 적절한 비즈니스 로직을 처리하고, 결과를 HTML, JSON, XML 등 다양한 형식으로 반환해야합니다.
문제 상황:
- 요청 처리와 응답 구성이 명확하지 않으면 코드가 복잡해지고 유지보수가 어려워짐
- 요청과 응답에 대한 로직이 비즈니스 로직과 섞이면서 관심사 분리가 어려워짐
문제 발생
기존 방식의 한계:
- JSP, Servlet만 사용하면 Controller, View , Model 간의 역할 구분이 명확하지 않아 코드가 복잡해진다.
- 요청 처리와 응답 작성 코드가 하나의 클래스에 섞여 있어 유지보수가 힘들다.
- URL 매핑 패턴이나 요청 파라미터 처리를 일일이 코드로 작성해야한다. (중복 코드 발생 및 관심사 섞임)
- 다양한 포멧(JSON,XML)으로 작성하기 어렵고, 반복 코드가 많아진다.
- 다양한 포멧별로 처리하는 서블릿이나 JSP파일이 늘어난다.
예시
- 서블릿 코드에서 doGet(),do Post() 메서드에 비즈니스 로직과 뷰 랜더링 코드가 섞임.
- 특정 URL에 대한 요청 처리를 하려면 web.xml에 하나하나 매핑을 추가해야한다.
- JSON 응답을 작성하려면 JSON문자열을 작성해야한다.
문제 파악
근본 원인
- 요청과 응답처리 / 비즈니스 로직 / 뷰 렌더링의 관심사의 분리가 섞여있다.
- URL 매핑, 요청 파라미터 처리, 응답 작성에 반복된 코드가 필요하다.
- 다양한 응답 포멧을 일관되게 처리하기가 어렵다.
결과
코드 재사용성이 낮고, 유지보수할 때 변경 범위가 넓어져 확장시 테스트 범위와 영향 범위가 커진다. 그러다보니 요구사항 변경에 유연하게 대응하기가 어렵다.
해결 원칙 수립
해결 원칙
- MVC 아키텍처를 도입하여 MVC, View , Controller 역할을 명확히 분리한다.
- 요청과 응답 처리를 표준화하고, URL 매핑과 요청 파라미터 바인딩을 자동화하여 반복 코드를 줄인다.
- 다양한 포멧의 응답을 일관된 방식으로 변환하는 구조 설계가 필요하다.
관심사 분리를 통해 유지보수와 확장성을 끌어 올린다. 관심사가 분리되면서 객체지향 프로그래밍의 장점인 유지보수성과 확장성을 가져올 수 있습니다. 역할에 의존하도록 코드를 수정하면 된다.
문제 해결
- 관심사 분리 방법으로 관심사가 같은 메서드끼리 클래스로 분리한다.
- 사용하는 오브젝트에서 의존 객체를 직접 의존하면 교체도 어렵고 강한 결합이 생기며, 변경도 어렵다.
- 따라서, 스프링 컨테이너를 활용하여 관심사 주입을 받아 해결을 한다.
정리
- 관심사 분리를 통해서 유지보수와 테스트가 편해진다.
- URL 매핑, 요청 파라미터 바인딩, 데이터 검증 등 반복적인 작업을 표준화하여 제공하기에 생산성이 올라간다.
- 다양한 응답 포멧을 일관된 방식으로 변환이 가능해진다 따라서 API 확장이 가능하다.
발생할 수 있는 문제
멀티쓰레드 문제
Spring MVC는 멀티쓰레드 기반 처리 모델입니다.
Spring MVC는 쓰레드 퍼 리퀘스트 방식입니다.
요청 1개당 쓰레드 1개를 할당해서 처리하고, 쓰레드가 작업을 완료할 때까지 블로킹 상태로 유지된다.
쓰레드는 반납하기 전까지 해당 요청만 처리하며, 한 번 할당된 쓰레드는 메모리와 CPU의 자원을 점유한다.
비유
스프링 MVC 는 유지보수를 쉽게 하기 위해서 관심사 분리를 통해 확장성과 유지보수가 쉽도록 구조를 나누었습니다.
저는 스프링MVC는 음식점이라고 생각합니다.
키오스크(Dispatcher Servlet)에서 주문을 하면 대기표를 받습니다.
주방(컨트롤러)에서 메뉴 전담 직원(서비스)에게 주문을 전달합니다.
음식이 나오기 전까지 외부는 춥고 주문 결과를 확인하기 위해 매장 내에서 손님들은 대기(블로킹 자원 점유)를 합니다.
댓글남기기