스프링을 사용하고 있지만 누군가 '스프링이 뭐야?' 라고 물어본다면, 과연 난 대답 할 수 있을까?
대답은 역시 No였다. 스프링을 '사용하는 법'은 알아도 스프링을 이해하고 있는 것은 아니였던 것 같다.
면접을 준비하며 스프링에 대해 생각하며 백지에 써내려간 '내가 이해한 스프링'을 먼저 적어본다.
스프링이 뭘까?
스프링은 framework이고, framework은 개발자들이 좀 더 쉽고 편리하게 애플리케이션을 개발할 수 있도록 미리 갖춰진 구조를 말한다.
framework이 없었다면 개발자들은 처음부터 끝까지 직접 모든 구조를 만들어 내야 할 것이다.
즉 만들어진 프로그램의 성능은 개발자의 역량에 따라 극명히 갈리게 된다. framework은 결국 그런 개발자들의 실력의 간극을 메꿔주는 장치라고도 볼 수 있다.
스프링 프레임워크의 핵심은 스프링 컨테이너이너이다.
스프링 컨테이너는 객체를 생성해주고, 객체간의 관계를 맺어주는 등의 관리자 역할을 한다.
서버는 항상 많은 사람들이 사용하고, 그들이 이용하는 비즈니스 로직은 대부분 동일하다.
각각의 사용자들이 동일한 비즈니스 로직을 이용하는데 그 오브젝트를 매번 만들어낸다면 비효율적이고 서버에 큰 부담이 될 것이다. 스프링 컨테이너는 그런 문제를 해결하기 위해 객체를 singleton으로 만들어 하나의 객체를 모두가 공유할 수 있도록 해준다.
스프링이 관리해야할 오브젝트(빈)라고 설정정보에 어필만 해준다면, 스프링은 그 설정정보를 참고하여 객체를 생성,관리하고 그 관계를 맺어준다.핵심은 개발자가 new 연산자 등을 통해 객체를 생성할 필요가 없다는 것이다. 개발자 입장에서는 스프링 컨테이너에게 그 참조변수만 일러준다면(@autowired) 스프링이 알아서 객체를 생성해주고 관계를 맺어준다. 이를 '의존성주입(DI)'라고 한다.
만일 다른 비즈니스로직을 사용하고 싶다면, 개발자는 Java코드를 건드리는게 아니라 설정파일만 변경해주면 컨테이너가 알아서 처리 해준다.
개발자가 직접 생성하고, 그 객체의 메서드를 사용하고, 또 그안에 다른 객체를 만드는 등 개발자가 제어권을 가지고 진행해야 했던 프로세스를 스프링이 모두 대신 제어해 주기 때문에 이를 '제어의 역전(IoC)'이라고 부른다.
스프링의 또다른 특징은 AOP(Aspect Object Programming)를 할 수 있게 한다는 것이다.
AOP는 어떤 공통된 로직을 따로 분리하여 필요할때 가져다 쓸 수 있는 구조로, 코드의 중복을 제거하는데 의의가 있다.
예를 들어, 트랜잭션을 처리하는데 필요한 예외처리나, commit, rollback처리같은 코드를 따로 분리하여 트랜잭션 처리가 필요한 작업(핵심로직)과 합쳐주는 것이다.
이렇게 된다면 트랜잭션 처리가 필요한 작업들 마다 예외처리 등의 코드를 일일이 넣으며 중복된 코드를 작성할 필요없이 가져다 합치기만 하면 된다. 스프링에선 이를 @Transactional 어노테이션으로 처리해주고 있다.
AOP는 특정 모듈 안이 아닌 모듈에 관계없이 애플리케이션 전체에서 공통적으로 쓰는 것이 핵심이다.
우리가 사용하는 Spring security도 내부적으로 AOP가 적용됐다. (권한체크는 전체 페이지에서 이루어져야 하고 이를 모든 작업에 코드를 넣어주는 것이 아닌, 따로 분리시켜 모든페이지에서 사용할 수 있는 것이다.)
▶ 모델1 방식이란?
JSP에 비즈니스 로직과 화면영역을 함께 구현하는 방식. (비즈니스 로직과 화면을 분리하지 않은 방식)
비즈니스 로직이 복잡하지 않거나 소규모 프로젝트일 경우 빠르고 쉽게 개발할 수 있다는 장점이 있지만, 출력을 위한 뷰 코드와 로직처리를 위한 자바 코드가 함께 섞여있기 때문에 JSP코드 자체가 복잡하고, 분업에 용이하지 않으며 유지보수가 어렵다.
▶ 모델2 방식이란?
화면과 비즈니스 로직이 분리되어있는 방식.
화면출력을 위한 뷰 코드는 JSP에서, 로직 처리를 위한 자바코드는 Servlet에서 처리하도록 분리하기 때문에 분업이 용이하고 유지보수가 쉽다.
▶ MVC패턴이란?
데이터를 의미하는 Model, JSP와 같이 실질적으로 보여지는 페이지의 View, 그리고 클라이언트의 Request를 처리하고 View와 Model사이의 중간 통신 역할을 하는 Controller의 3가지 형태로 구분하여 소프트웨어를 개발하는 방법론.
모델2 방식은 MVC패턴을 따른 것이다.
▶ 스프링이란?
Java 기반의 엔터프라이즈 Application 개발을 빠르고 편하게 할 수 있도록 도와주는 경량 프레임워크.
왜 '경량' 프레임워크인가?
초기 서버사이드 처리는 직접 쓰레드, 소켓연결 등을 개발자들이 직접 처리했고, 개발자 마다 구현하는 방법이 다 달라 협업에 불편함이 많았다.
이런 개발 표준을 잡은것이 Java Enterprise Edition. 그리고 그 안에 많은 스펙들을 담았고, 개발자들은 그 스펙들을 구현하는 방법을 사용하기 시작했다. Servlet/JSP도 그 중 하나이다.
그러나 이 구현방법 또한 여러가지 방법으로 나뉘게 되고, 개발자들은 또 정형화, 표준화 된 방법을 찾기 시작했다.
그래서 등장한 것이 Framework이다.
많은 종류의 Framework이 등장하고 자바 진영에서는 대표적으로 EJB가 나왔지만 분산환경 처리에 특화된 EJB는 너무 무거운데다 불편한 점이 많았고, 이런 EJB에 반기를 들고 탄생한 '경량화'된 Java 엔터프라이즈용 Framework이 Spring인 것이다.
왜 스프링을 사용하는가?
스프링은 Framework이고, Framework은 개발자들이 좀 더 쉽고 편리하게 애플리케이션을 개발할 수 있도록 미리 갖춰진 구조를 말한다. Framework이 없었다면 개발자들은 처음부터 끝까지 직접 모든 구조를 만들어내야 할 것이다.
즉, 만들어진 프로그램의 성능은 개발자의 역량에 따라 극명히 갈리게 된다.
스프링은 Application 개발에 필요한 하부 구조를 포괄적으로 제공함에 따라 개발자들의 실력의 간극을 메꿔줄 수 있는 데다가 올바른 형태의 코드만 넣어준다면 일정 수준의 성능과 안정성을 보장해 줄 수 있다. 그 틀과 구조 위에서 개발자들은 핵심 비즈니스 로직에만 집중할 수 있어서 생산성 또한 향상된다.
▶ IoC란?(Inversion of Control : 제어의 역행)
객체에 대한 제어권이 개발자에게 있는 것이 아닌, 스프링 컨테이너에게 있는 것. 인스턴스의 생성부터 소멸까지의 라이프싸이클 관리 등을 컨테이너가 대신 해준다.
일반적으로 프로그램의 흐름은 main()메서드처럼 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정하고, 생성하고, 오브젝트의 메서드를 호출하고, 그 메서드 안에서 다음에 사용할 것을 결정하는 식의 작업이 반복되는데, 이런 구조는 모든 종류의 작업을 '사용하는 쪽'에서 제어하는 구조다. 이런 구조가 역전된 것이 IoC이고, IoC에서는 오브젝트가 모든 제어 권한을 자신이 아닌 다른 대상에게 위임한다.
스프링프레임워크에서는 애플리케이션 코드가 프레임워크에 의해 사용되어지는 구조인데, 프레임워크 위에 개발한 클래스를 등록해 두고, 프레임워크가 흐름을 주도하는 중에 개발자가 만든 애플리케이션 코드를 사용하는 방식으로, 애플리케이션 코드는 프레임워크가 짜놓은 틀 안에서 수동적으로 동작한다고 볼 수 있다. 즉, 코드가 직접 능동적으로 동작하는 방식이 아닌, 그 제어의 권한을 프레임워크에게 위임한 방식이라고 할 수 있다.
스프링에서는 애플리케이션 컨텍스트가 빈의 생성과 관계설정 같은 제어를 담당한다.
▶ DI란?(Dependency Injection : 의존성 주입)
제어의 역행(IOC)으로 특정 객체에 필요한 다른 객체를 외부에서 결정해서 연결시키는 것.
'이건 스프링이 관리해야할 오브젝트(빈)야!' 라고 설정만 해준다면(applicationContext.xml) 스프링은 그 설정 정보를 참고해서 객체를 생성,관리하고 그 관계를 맺어준다.
핵심은 개발자가 new 연산자 등을 통해 객체를 생성할 필요가 없다는 것이다(제어의 역행-IoC). 개발자 입장에서는 스프링 컨테이너에게 그 참조변수만 일러준다면(@Autowired나 setter주입 등) 스프링이 알아서 객체를 생성해주고, 관계를 맺어준다. 이를 의존성 주입(DI : dependency Injection)이라고 하며 개발자는 자신의 코드에 필요한 객체를 스프링을 통해 주입받는 구조로 코드를 작성한다.
▶ Bean Factory(빈팩토리)/Application Context(애플리케이션 컨텍스트)란?
빈 팩토리 : 빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트.
애플리케이션 컨텍스트 : IoC 방식을 따라 만들어진 일종의 빈 팩토리.
빈 팩토리는 빈을 등록하고, 생성하고, 조회하고 돌려주고, 그 외에 부가적인 빈을 관리하는 기능을 담당하지만 보통은 이 빈 팩토리를 바로 사용하지 않고 이를 확장한 애플리케이션 컨텍스트를 이용한다.
애플리케이션 컨텍스트는 빈 팩토리를 확장한 IoC 컨테이너로, 빈을 등록하고 관리하는 기본 기능은 빈 팩토리와 동일하나 스프링이 제공하는 각종 부가 서비스를 추가로 제공한다.
빈 팩토리와 애플리케이션 컨텍스트는 거의 동일하다고 볼 수 있다. 빈 팩토리라고 말하면 빈을 생성하고 관계를 설정하는 IoC의 기본 기능에 초점을 맞춘 것이고, 애플리케이션 컨텍스트라고 말할 때는 애플리케이션 전반에 걸쳐 모든 구성요소의 제어 작업을 담당하는(스프링이 제공하는 애플리케이션 지원 기능을 모두 포함한) IoC 엔진이라는 의미가 좀 더 부각된다.
▶ 스프링 컨테이너(Spring Container)란?
빈의 생성,관계설정,생명주기 등을 관장하는 컨테이너.
객체(빈)관리의 관점에서 Application Context를 스프링 컨테이너라고 부른다.
Application Context는 그 자체로 ApplicationContext 인터페이스를 구현한 오브젝트를 가리키기도 하는데, 그러한 오브젝트는 하나의 애플리케이션에서 보통 여러 개가 만들어져 사용되고, 이를 통틀어서 스프링 컨테이너라고 볼 수 있다.
▶ 빈(Bean)이란?
스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트.
오브젝트 단위의 애플리케이션 컴포넌트이다. 동시에 스프링 빈은, 스프링 컨테이너가 생성과 관계설정, 사용 등을 제어해주는 IoC가 적용된 오브젝트를 가리키는 말이다.
스프링을 사용하는 애플리케이션에서 만들어지는 모든 오브젝트가 다 빈은 아니고, 스프링이 직접 생성과 제어를 담당하는 오브젝트만을 빈이라고 부른다.
POJO와 설정(Configuration. xml이나 어노테이션)을 Spring의 컨테이너에 주입시키면 Bean으로 등록되고 사용할 수 있다.
▶ 빈 스코프(Bean Scope)란?
스프링이 관리하는 빈이 생성되고, 존재하고, 적용되는 범위.
스프링 빈의 기본 스코프는 싱글톤이다. 싱글톤 스코프는 컨테이너 내에 한 개의 오브젝트만 만들어져서, 강제로 제거하지 않는 한 스프링 컨테이너가 존재하는 동안 계속 유지된다. 경우에 따라서는 싱글톤 외의 스코프를 가질 수 있는데 대표적으로 프로토타입 스코프가 있다. 프로토타입은 싱글톤과 달리 컨테이너에 빈을 요청할때마다 매번 새로운 오브젝트를 만들어 준다. 스코프는 xml과 어노테이션 설정으로 가능하다.
빈 스코프의 종류
- Singleton : 스프링 컨테이너 내에 단 하나의 객체만 존재. 컨테이너가 사라질 때 제거됨. (상태가 없는 공유객체나 읽기 전용 공유객체에 적합)
- Prototype : 모든 요청에 대해 새로운 객체를 생성. 참조가 사라지면 GC(가비지 컬렉터)에 의해 제거됨. (상태가 노출되지 않은 객체-다른 의존객체와는 독립적으로 작업을 수행하는 객체-에 적합)
- Request : HTTP Request의 생명주기와 같음. 웹을 통해 새로운 HTTP 요청이 생길 때마다 생성됨. 하나의 HTTP Request는 자신만의 객체를 가짐.
- Session : HTTP Session의 생명주기와 같음.
왜 스프링 빈은 기본적으로 싱글톤일까?
Spring Framework의 핵심은 스프링 컨테이너. 이 컨테이너는 객체를 갖고 있다가 필요할때 주입한다. 왜 그렇게 동작할까? 서버는 많은 사람들이 사용하고 그 사용자들이 이용할 비즈니스 로직은 대부분 동일하다.
동일한 비즈니스 로직(빈)이 이용하는 사람들마다 하나씩 생성된다면 서버는 부하에 걸리기 쉽고 애초에 동일한 로직이 여러개 생성될 필요가 없기 때문에 스프링에서는 빈들을 싱글톤으로 관리한다.
▶ POJO(Plain Old Java Object)란?
어느 곳에 종속되지 않은 순수한 자바 객체.
과거에 자바로 웹 애플리케이션을 만들기 위해 Servlet클래스를 상속받아 구현했어야 했다. 서블릿 컨테이너 안에서 서블릿으로 존재하기 위해서는 그 구현이 강제되었던 것이다.
그렇게 강제된 구현으로 만들어진 서블릿 객체는 서블릿 컨테이너 환경에서 사용되어질 수 있다. 이는 그 환경에 종속 되어 있기에 POJO라고 할 수 없다.
어느 곳에 종속되지 않는다는 의미는, 해당 클래스를 사용하기 위해 외부 환경(like 프레임워크)이 필요하고, 해당 환경이 특정 인터페이스를 구현할 것을 강요하는 등의 제약에서 자유롭다는 것을 의미한다.
(따라서 단순히 외부 구동환경과 무관한 다른 클래스의 상속 또는 구현은 상관 없다.)
즉, 다시말해 POJO는 외부환경(like Spring MVC)을 걷어내도 정상적으로 작동이 되어야 한다는 것이다.
Spring은 개발자가 직접 위와같이 Servlet클래스를 작성하지 않고 POJO만으로 웹 애플리케이션을 구축할 수 있다는 것이 특징이다.(개발자가 비즈니스로직만 신경 쓸 수 있다)
* REFERENCE :
[도서] 토비의 스프링 3.1 스프링의 이해와 원리
[TISTORY] 기억보단 기록을 - ServletContainer? DI Container? Bean? POJO? (https://jojoldu.tistory.com/28)
'Tech > Web' 카테고리의 다른 글
HTTP 웹의 기초 (0) | 2020.04.02 |
---|---|
IntelliJ에서 스프링 프로젝트 생성 및 설정하기(Gradle, Tomcat, MyBatis, Oracle, Java Configuration) (0) | 2020.03.23 |
컨테이너가 Http Request를 다루는 방법. 동작 순서 (0) | 2020.03.04 |
Spring framework이 없었다면? (0) | 2020.01.20 |
JPQL과 QueryDSL (0) | 2019.12.01 |
댓글