10 min to read
[Spring]Spring MVC 개념 정리
Spring MVC 개념 정리
[스프링(Spring)의 정의]
스프링이란 자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크 이며, 아래와 같은 주요 특징들을 가지고 있다. 1) 애플리케이션 프레임워크
- 애플리케이션 프레임워크는 특정 계층이나, 기술, 업무 분야에 국한되지 않고, 애플리케이션의 전 영역을 포괄하는 범용적인 프레임워크를 말한다. 애플리케이션 프레임워크는 애플리케이션 개발의 전 과정을 빠르고 편리하며 효율적으로 진행하는데 일차적인 목표를 두는 프레임워크다. 또한 애플리케이션의 전 영역을 관통하는 일관된 프로그래밍 모델과 핵심 기술을 바탕으로 해서 각 분야의 특성에 맞는 필요를 채워주고 있다.
2) 경량급
- 스프링이 경량급이라는 건 스프링이 아주 가볍다는 뜻은 아니며, 스프링이 처음 등장할 당시 주류 기술이었던 EJB 같은 과도한 엔지니어링이 적용된 기술과 스프링을 대비시켜 설명하려고 사용했던 표현이다(불필요하게 무겁진 않다). 스프링의 장점은 가장 단순한 서버 환경인 톰캣(Tomcat)이나 제티(Jetty)에서도 완벽하게 동작하며, 단순 개발툴과 기본적인 개발환경으로도 엔터프라이즈 개발에서 필요한 주요기능을 갖춘 애플리케이션을 개발하기에 충분하다(복잡한 EJB와 고가의 WAS를 갖춰야만 가능했단 엔터프라이즈 개발의 고급기술을 대부분 사용가능). 때문에 생산성과 품질 면에서 유리하다.
3) 자바 엔터프라이즈 개발을 편하게
- 스프링은 근본적인 부분에서 엔터프라이즈 개발의 복잡함을 제거하고, 진정으로 개발을 편하게 해주는 해결책을 제시한다. 편리한 애플리케이션 개발이란 개발자가 복잡하고 실수하기 쉬운 로우레벨 기술에 많은 신경을 쓰지 않으면서도 애플리케이션 핵심인 사용자의 요구사항, 즉 비즈니스 로직을 빠르고 효과적으로 구현하는 것을 말한다.
4) 오픈소스
- 오픈소스란 말 그대로 소스가 모두에게 공개되고, 특별한 라이선스를 취득할 필요없이 얼마든지 자유럽게 이용해도 된다는 뜻이다. 소스를 자유롭게 열람하고 자신의 목적에 맞고 사용할 수 있을 뿐만 아니라, 필요하면 맘대로 수정할 수 있고, 수정된 제품과 소스를 다시 공개적으로 배포하는 자유도 허용된다. 스프링에 적용된 오픈소스 라이선스는 비교적 제약이 적고 사용이 매우 자유로운 편인 아파치 라이선스 버전 2.0(Apache)이다. 오픈소스의 장점은 공개된 커뮤니티의 공간 안에서 투명한 방식으로 다양한 참여를 통해 개발되기 때문에 매우 빠르고 유연한 개발이 가능하다. 단점으로는 오픈소스이기 때문에 지속적이고 안정적인 개발이 지속될지가 불확실하다는 것이다(개발자에 극히 의존적). 단 스프링 개발업체인 스프링소스(SpringSource)가 2009년에 세계적인 IT 기업인 VMWare와 전략적으로 합병해서 이전보다 더욱 안정된 환경에서 오픈소스 스프링 개발에 더욱 전념하고 있다. 때문에 스프링은 오픈소스의 장점을 충분히 취하면서 단점과 한계를 잘 극복하고 있는, 전문적이고 성공적인 오픈소스 소프트웨어라 할 수 있다.
[스프링의 목적]
1) 엔터프라이즈 개발의 복잡함
- 기술적인 제약조건과 요구사항을 고려하면서 애플리케이션을 개발해야 하는 부담(서버 자원의 효율적인 공유 및 분배. 뛰어난 서비스 안정성 및 확장성. 타 시스템과의 자동화된 연계 및 리클라이언트와의 접속을 위한 리모팅 기술. 분산 트랜잭션 지원 등)
- 비즈니스 로직의 복잠함 증가(컴퓨터를 이용하지 않고는 업무 진행이 힘들만큼 엔터프라이즈 시스템에 대한 업무 의존도가 높아짐. 업계의 추이에 따라서 수시로 업무 프로세스를 변경하고 조종하는 것을 상시화할 만큼 변화의 속도가 빨라짐. 애플리케이션이 자주 수정되는 시대)
- 전통적인 자바 엔터프라이즈 개발기법은 대부분의 비즈니스 로직의 복잡한 구현코드와 기술적인 코드가 혼재되어 전체적인 복잡함음 몇배로 가중됨
2) 복잡함을 해결하려는 도전
- EJB : 기술적인 복잡함을 애플리케이션의 핵심 로직에서 일부분 분리하는데는 성공(선언적 트랜잭션, 선언적 보안, 컨테이너를 통한 리모팅 기술 적용, 컴포넌트 단위의 배치, 컴포넌트 생명주기 관리 등). 하지만 EJB 틀 안에서 자바 코드를 만들게 강제함으로서 자바 본래의 장점을 잃게 하였음(EJB의 특정 클래스를 상속하게 함으로써 더이상 상속구조 적용하지 못하게 함. 다형성 적용 제한 등). 침투기술(어떤 기술을 적용했을 때 그 기술과 관련된 코드나 규약이 코드에 등장함)
- 스프링(Spring) : 비침투적인(non-invasive) 방식을 통한 효과적인 해결책. 기술의 적용 사실이 코드에 직접 반영되지 않는다는 것이 특징. 기술적인 복잠함과 비즈니스 로직을 다루는 코드를 깔끔하게 분리 가능
3) 복잡함을 상대하는 스프링의 전략
- 기술적 복잡성을 상대하는 전략
- 서비스 추상화 : 기술에 대한 접근방식이 일관성이 없고 특정 환경에 종속적인 문제에 대응하기 위하여, 기술적인 복잡함은 서비스 추상화를 통해 로우레벨의 기술 구현 부분과 기술을 사용하는 인터페이스로 분리하고, 환경과 세부 기술에 독립적인 접근 인터페이스를 제공함. 자바메일과 같이 테스트가 어려운 기술에 대해서도 서비스 추상화를 통해 테스트 편의성을 증대시키고, 기술에 대한 세부설정과 환경으로부터 독립적인 코드 생성 가능. 데이터 엑세스 예외에 대한 추상화는 비즈니스 로직을 담은 서비스 레이어의 코드가 특정 기술이 발생시키는 예외에 종속되지 않고, 불필요하게 예외를 잡아야 하거나 throws를 선언해야 하는것을 방지해줌.
- AOP : 기술과 비즈니스 로직의 혼재로 발생하는 복잡함을 해결하기 위한 스프링의 접근 방법. AOP는 최수까지 애플리케이션 로직을 담당하는 코드에 남아 있는 기술 관련 코드를 깔끔하게 분리해서 별도의 모듈로 관리하게 해주는 강력한 기술임. AOP는 기술을 다루는 코드로 인한 복잡함을 기술 그 자체 이상으로 불필요하게 증대되지 않도록 도와주는 가장 강력한 수단.
- 비즈니스와 애플리케이션 로직 복잠성을 상대하는 전략
- 객체지향 : DB에 비즈니스 로직을 두는 건 매우 불편하고 위험한 일. 데이터 분석 및 가공, 로직 처리 부분은 확장이 용이하고 비용이 싼 애플리케이션 서버 쪽으로 이동 -> 객체지향 언어의 장점을 잘 살려 비즈니스 로직의 복잡함을 효과적으로 다루자 -> 객체지향은 자바 기술의 가장 큰장점. 스프링의 모토는 결국 “기본으로 돌아가자”가 됨(EJB는 객체지향의 장점을 취하지 못했음)
- DI : 특별한 기술이라기 보다는 유연하게 확장할 수 있는 오브젝트 설계를 하다보면 자연스럽게 적용하게 되는 객체지향 프로그래밍 기법. 스프링은 단지 그것을 더욱 편하게 사용하도록 도와줌. 기술적인 복잡함을 해결하는 문제나 기술적인 복잡함이 비즈니스 로직에 침범하지 못하도록 분리하는 경우에는 DI가 바탕이 된 여러가지 기법이 활용됨. 반면에 비즈니스 로직 자체의 복잡함을 해결하려면 DI보단 객체지향 설계기법이 더 중요함.
[POJO란 무엇인가?]
1) POJO의 정의
- POJO는 Plain Old Java Object의 약어
2) 스프링의 핵심 : POJO
- 스프링 핵심 개발자들은 “스프링의 정수(essence)”는 엔터프라이즈 서비스 기능(보안, 트랜잭션 등)을 POJO에 제공하는 것” 이라고 함.
- 엔터프라이즈 서비스 기술을 POJO에 제공한다는 말은, 뒤집어 생각해보면 엔터프라이즈 서비스 기술과 POJO라는 어플리케이션 로직을 담은 코드를 분리했다는 뜻.
- ‘분리됐지만 반드시 필요한 엔터프라이즈 서비스 기술을 POJO 방식으로 개발된 애플리케이션 핵심 로직을 담은 코드에 제공한다’는 것이 스프링의 가장 강력한 특징과 목표.
3) POJO의 조건
- 특정 규약에 종속되지 않는다.
- POJO는 자바 언어와 꼭 필요한 API 외에는 종속되지 않아야 한다. 특정 규약을 따라 만들게 하는 경우는 대부분 규약에서 제시하는 특정 클래스를 상속하도록 요구한다. 그럴 경우 자바의 단일 상속 제한 때문에 더 이상 해당 클래스에 객체지향적인 설계 기법을 적용하기가 어려워지는 문제가 생긴다. 또한 규약이 적용된 환경에 종속적이 되기 때문에 다른 환경으로 이전이 힘들다는 문제점이 있다.(EJB2는 POJO가 아님)
- 특정 환경에 종속되지 않는다.
- 어떤 경우는 특정 벤더의 서버나 특정 기업의 프레임워크 안에서만 동작 가능한 코드로 작성되기도 한다. 또 환경에 종속적인 클래스나 API를 직접 쓴 경우도 있다. 순수한 애플리케이션 로직을 담고 있는 오브젝트 코드가 특정 환경에 종속되게 만드는 경우라면 그것 역시 POJO라고 할 수 없다. POJO는 환경에 독립적이어야한다. 특히 비즈니스 로직을 담고 있는 POJO 클래스는 웹이라는 환경정보나 웹 기술을 담고 있는 클래스나 인터페이스를 사용해서는 안된다. 비즈니스 로직을 담은 코드에 HttpServletRequest나 HttpSession, 캐시와 관련된 API가 등장하거나 웹 프레임워크의 클래스를 직접 이용하는 부분이 있다면 그것은 진정한 POJO라고 볼 수 없다. 단지 자바의 문법을 지키고, 순수하게 JavaSE API만을 사용했다고 해서 그 코드를 POJO라고 할 수는 없다. POJO는 객체지향적인 자바 언어의 기본에 충실하게 만들어져야 하기 때문이다
4) POJO의 장점
- 오브젝트가 특정한 기술과 환경에 종속되지 않는 깔끔한 코드(로우레벨의 기술과 환경에 종속적인 코드가 비즈니스 로직과 함께 섞이지 않음)
- 환경의 제약이 없기 때문에 자동화된 테스트에 유리
- 객체지향적 설계를 자유롭게 적용할 수 있음
5) POJO 프레임워크
- 스프링은 POJO를 이용한 엔터프라이즈 애플리케이션 개발을 목적으로 하는 프레임워크이다. POJO 프로그래밍이 가능하도록 기술적인 기반을 제공하는 프레임워크를 POJO 프레임워크라고 한다. 스프링은 엔터프라이즈 애플리케이션 개발의 모든 영역과 계층에서 POJO 방식의 구현이 가능하게 하려는 목적으로 만들어졌다. 스프링을 이용하면 POJO 프로그래밍의 장점을 그대로 살려서 엔터프라이즈 애플리케이션의 핵심 로직을 객체지향적인 POJO를 기반으로 깔끔하게 구현하고, 동시에 엔터프라이즈 환경의 각종 서비스와 기술적인 필요를 POJO 방식으로 만들어진 코드에 적용할 수 있다. 스프링은 비즈니스 로직의 복잡함과 엔터프라이즈 기술의 복잡함을 분리해서 구성할 수 있게 도와준다. 하지만 자신은 기술영역에만 관여하지 비즈니스 로직을 담당하는 POJO에서는 모습을 감춘다. 데이터 액세스 로직이나 웹 UI 로직을 다룰 때만 최소한의 방법으로 관여한다. POJO 프레임워크로서 스프링은 자신을 직접 노출하지 않으면서 애플리케이션을 POJO로 쉽게 개발할 수 있게 지원해준다.
[스프링의 기술]
1) 제어의 역전(IoC)/의존관계주입(DI)
- IoC란? Inversion of Control(제어의 역전)의 약자로 일반적으로는 모든 종류의 작업을 사용하는 쪽에서 제어(객체의 생성과 소멸) 하지만 IoC는 제어 흐름의 개념을 거꾸로 뒤집어서 컨테이너가 내가 작성한 코드의 제어를 대신 해주는 것을 의미한다. 때문에 오브젝트는 자신이 사용할 오브젝트를 스스로 생성하거나 선택하지 않는다. 그리고 자신이 어떻게 만들어지고 어디서 사용되는지 알수 없다.
- DI란? Dependency Injection(의존성 주입)의 약자로 각 계층 사이, 각 클래스 사이에 필요로 하는 의존 관계를 컨테이너가 자동으로 연결해주는 것. Spring에서 IoC를 제공하는 형태 중 하나. 의존관계가 발생함으로서 결합도를 낮춰, 코드 수정을 피할 수 있다.
- 두 개의 오브젝트를 분리해서 만들고, 인터페이스를 두고 느슨하게 연결한 뒤, 실제 사용할 대상은 DI를 통해 외부에서 지정하는 이유(new 키워드로 생성해서 사용하는 강한 결합을 쓰는 방법보다 나은 점)? 유연한 확장이 가능하게 하기 위함. DI는 개발폐쇄원칙(OCP)라는 객체지향 설계 원칙으로 설명됨. 유연한 확장이라는 장점은 OCP의 “확장에는 열려있다(개방)” 에 해당. DI는 역시 OCP의 “변경에는 닫혀있다(폐쇄)”라는 말로도 설명이 가능. 폐쇄관점에서 볼 때 장점은 “재사용이 가능하다”라고 볼수 있음.
- DI의 활용방법
- 핵심 기능의 변경 : 의존하는 대상이 가진 핵심 기능을 DI 설정을 통해 변경하는 것이 대표적인 DI 활용방법.
- 핵심 기능의 동적인 변경 : DI는 동적인 방식으로 연결되지만 한번 DI되면 바뀌지 않는 정적인 관계를 맺어줌. 하지만 DI를 잘 활용하면 애플리케이션이 동작하는 중간에 그 의존 대상을 다이나믹하게 변경 가능.
- 부가기능의 추가 : 인터페이스를 두고 사용하고, 실제 사용할 오브젝트는 외부에서 주입하는 DI를 적용해두면 데코레이션 패턴을 쉽게 적용할 수 있음. 그래서 핵심기능과 클라이언트 코드에는 전혀 영향을 주지 않으면서 부가적인 기능을 얼마든지 추가할 수 있음.
- 인터페이스의 변경 : 서비스추상화(PSA)처럼 인터페이스가 다른 다양한 구현을 같은 방식으로 사용하도록, 중간에 인터페이스 어댑터 역할을 해주는 레이어를 하나 추가하는 방법도 있음. PSA는 클라이언트가 일관성 있게 사용할 수 있는 인터페이스를 정의해주고 DI를 통해 어댑터 역할을 하는 오브젝트를 이용하게 해준다.
- 프록시 : 필요한 시점에 실제 사용할 오브젝트를 초기화하고 리소스를 준비하게 해주는 지연된 로딩(lazy loading)을 적용하거나, 원격 오브젝트를 호출할 때 마치 로컬에 존재하는 오브젝트처럼 사용할 수 있게 해주는 원격 프록시를 적용할 때 프록시가 필요하며 두 방법 모두 DI를 필요로 한다.
- 템플릿과 콜백 : 반복적으로 등장하지만 항상 고정적인 작업 흐름과 그 사이에 자주 바뀌는 부분을 분리해서 템플릿과 콜백을 만들고 이를 DI 원리를 응용해 적용하면 코드를 간결하게 만들 수 있다.
- 싱글톤과 오브젝트 스코프 : DI를 프레임워크로 이용한다는건 DI 대상 오브젝트를 컨테이너가 관리한다는 의미다. 오브젝트의 생성부터 관계설정, 이용, 소멸에 이르기까지 모든 과정을 DI 컨테이너가 주관하기 때문에 그 오브젝트의 스코프를 자유롭게 제어할 수 있다. 스프링의 DI는 기본적으로 싱글톤으로 오브젝트를 만들어서 사용한다. 컨테이너가 알아서 싱글톤으로 만들고 관리하기 때문에 클래스 자체는 싱글톤을 고려하지 않고 자유롭게 설계 가능하다.
- 테스트 : 다른 오브젝트와 협력해서 동작하는 오브젝트를 효과적으로 테스트하는 방법은 가능한 고립시키는 것이다. 즉 다른 오브젝트와의 사이에서 일어나는 일을 테스트를 위해 조작할 수 있도록 만든다. 복잡한 테스트할 대상에 의존하는 오브젝트를, 테스트를 목적으로 만들어진 목 오브젝트로 대체하면 유용하다.
2) AOP(Aspect-Oriented-Programming : 관점 지향 프로그래밍)
- AOP란? 기능을 핵심 비즈니스 로직과 공통 모듈로 구분하고, 핵심 로직에 영향을 미치지 않고 사이사이에 공통 모듈을 효과적으로 잘 끼워넣도록 하는 개발 방법.
- 객체지향 기술은 매우 성공적인 프로그래밍 방식이지만, 복잡해져가는 애플리케이션의 요구조건과 기술적인 난해함을 모두 해결하는데 한계가 있고, IoC/DI를 이용해서 POJO에 선언적인 엔터프라이즈 서비스를 제공할 수 있지만 일부 서비스는 순수한 객체지향 기법만으로는 POJO의 조건을 유지한채로 적용하기 힘들다. 이런 문제를 해결하기 위해 AOP가 필요하다.
- AOP를 자바 언어에 적용하는 기법
- 스프링과 같이 다이나믹 프록시를 사용하는 방법 : 기존 코드에 영향을 주지 않고, 부가기능을 적용하게 해주는 데코레이터 패턴을 응용한 것. 쉽고 적용이 간편하지만 부가기능을 부여할 수 있는 곳은 메소드의 호출이 일어나는 지점 뿐이라는 제약.
- 자바 언어의 한계를 넘어서는 언어의 확장을 하는 방법 : AspectJ라는 유명한 오픈소스 AOP 툴 활용(프록시 방식의 AOP에서는 불가능한 다양한 조인포인트 제공. 메소드 호출 뿐 아니라 인스턴스 생성, 필드 엑세스, 특정 호출 경로를 지닌 메소드 호출 등에도 부가기능 제공 가능)
- AOP가 사용되는 경우
- 간단한 메소드 성능 검사
- 트랜잭션 처리
- 예외 반환
- 아키텍쳐 검증
- 기타(로깅, 인증, 권한 등)
3) PSA(Portable-Service-Abstraction : 포터블 서비스 추상화)
- PSA란? 환경과 세부기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있게 해주는 스프링 기술
- POJO로 개발된 코드는 특정 환경이나 구현 방식에 종속적이지 않아야 한다. 스프링은 JavaEE를 기존 플랫폼으로 하는 자바 엔터프라이즈 개발에 주로 사용된다. 따라서 다양한 JavaEE 기술에 의존적일 수밖에 없다. 특정 환경과 기술에 종속적이지 않는다는 게 그런 기술을 사용하지 않는다는 뜻은 아니다. 다만 POJO 코드가 그런 기술에 직접 노출되어 만들어지지 않는다는 말이다. 이를 위해 스프링이 제공하는 대표적인 기술이 바로 일관성 있는 서비스 추상화 기술이다.
*출처 :
- 토비의 스프링 3.1 Vol.1 스프링의 이해와 원리
- https://jongmin92.github.io/2018/05/20/Spring/toby-8/
- https://12bme.tistory.com/157 참고
Comments