Spring의 주요 특징 및 핵심 개념
공부 배경
최근 유튜브 알고리즘으로 백기선님의 스프링 제대로 공부했는지 5분안에 확인 하는 방법 영상을 보게 되었고, 말 그대로 5분안에 내 실태를 확인하게 됐다…😅
그리고 이어서 이어진 영상들로
이 세 영상을 접하고 나서, Java 백엔드 개발자는 준비하는 사람으로써 Spring의 주요 기능과 핵심 개념에 대해 정리해야겠다고 생각했고, 이 역시 좋은 설명글을 접하게 되어 참고하여 정리해 보았다.
스프링(Spring)이란?
스프링 정의
엔터프리이즈용 Java 애플리케이션 개발을 편하게 할 수 있게 해주는 오픈소스 경량급 애플리케이션 프레임워크
엔터프라이즈용 Java 애플리케이션 개발을 편하게 할 수 있게 해주는
스프링은 이전 기술에 비해 사용 방법이 덜 복잡하여 개발 초기에 기본적인 설정과 적용시킬 기술들만 잘 선택한다면, 기술보다는 애플리케이션의 로직 자체에 더 집중하여 [^비즈니스로직]을 구현할 수 있다.
오픈소스
스프링은 모든 사용자에게 무료로 열려 있다. 즉, 어떤 개인 및 기업도 스프링을 사용하여 웹 애플리케이션을 개발할 수 있으며, 필요시에는 스프링 코드를 일부 수정하여 사용할 수 있다. 이처럼 오픈소스로 프로젝트를 공개해 놓으면 여러 사람이 프로젝트의 코드를 사용해봄으로써 다양한 검증 과정을 거칠 수 있다는 장점이 있다.
오픈소스로 배포되어 누구나 이용할 수 있지만, 스프링소스(SpringSource)라는 IT기업에서 관리하기 때문에,스프링은 오픈소스 프레임워크이지만, 안정적인 개발과 개선이 보장됩니다.
경량급
기존에 스프링 대신 사용하던 기술들과 비교하여, 스프링을 사용했을 때에 개발자가 작성해야 할 코드가 상대적으로 단순하다 .스프링을 사용함으로써 기존 기술을 사용할 때에 불가피하게 작성해야만 했던 불필요하게 복잡한 코드를 제거하여 코드의 복잡성을 낮출 수 있다.
애플리케이션 프레임워크
애플리케이션 프레임워크는 애플리케이션을 개발하는 데에 있어 필요한 모든 업무 분야 및 모든 기술과 관련된 코드들의 뼈대이다.
스프링의 특징
POJO 프로그래밍을 지향
POJO란, Plain Old Java Object, 즉 순수 Java만을 통해서 생성한 객체를 의미한다.
순수 Java 만을 사용한다는 것은 Java 및 Java의 스펙에 정의된 기술만 사용한다는 의미이다.
어떤 객체가 외부의 라이브러리나 외부의 모듈을 가져와서 사용하고 있다면, 그 객체는 POJO라고 할 수 없습니다. POJO는 말 그대로, 다른 기술을 사용하지 않는 순수한 Java만을 사용하여 만든 객체인 것이다.
POJO는 왜 중요할까? 외부 라이브러리를 import하여 라이브러리의 메서드를 사용하고 있는 객체가 있다고 가정해보자. 이 객체는 순수 Java 외에 외부 기술을 사용하고 있으므로, POJO가 아니다. 이 때, 이 객체가 사용하고 있는 기술이 더이상 사용되지 않거나(Deprecated), 더 개선된 신 기술이 등장하면 해당 기술을 사용하고 있는 모든 객체들의 코드를 전부 바꿔야한다.😣 이는 해당 객체가 외부 모듈에 직접적으로 의존하고 있기 때문에 자연스럽게 발생하는 문제이다.
반면, POJO는 순수 Java만을 사용하여 만든 객체이므로 특정 기술이나 환경에 종속되지 않는다. 외부 기술이나 규약의 변화에 얽매이지 않아, 보다 유연하게 변화와 확장에 대처할 수 있다. 이러한 POJO를 사용하여 비즈니스 로직을 구현하면 객체지향 설계를 제한없이 적용할 수 있으며, 코드가 단순해져 테스트와 디버깅 또한 쉬워진다. 이처럼 비즈니스 로직을 구현하는 데에 POJO를 적극적으로 활용하는 프로그래밍 패러다임을 POJO 프로그래밍이라고 한다.
POJO 프로그래밍을 위해 스프링이 지원하는 기술인 IoC/DI, AOP, PSA에 대해 알아보자.
IoC / DI (Inversion of Control / Dependency Injection, 제어의 역전 / 의존성 주입)
Java는 객체지향 언어이므로, 객체들 간의 관계를 적절히 맺어주는 것이 중요한 요소이다. A 인스턴스가 B 인스턴스의 메서드를 호출하고 있다면 A는 B와 의존 관계를 맺은 것이 되며, 이 둘의 관계를 “A가 B에 의존하는 관계”라고 표현할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class A {
public void methodOfA() {
B b = new B();
b.example();
C c = new c.example();
c.example();
...
}
}
class B {
public void example(){
...
}
}
class C {
public void example(){
...
}
}
...
그러나 개발자가 직접 new 키워드를 사용하여 인스턴스를 생성하게되면 수십 또는 수백개의 객체의 의존성을 부여할 경우, 코드 변경시 모든 코드를 수정해주어야 하는 문제가 생긴다.
하지만 스프링을 사용하면 변화가 발생한 상황에 최소한의 수정만으로 변화를 유연하게 수용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
interface I { // (1) A가 사용하는 메서드를 인터페이스 I의 추상 메서드로 정의(추상화)
void example();
}
class A {
private I i; // (3) 인터페이스 타입의 필드를 선언하고
public A(I i) { //(4) 생성자를 통해 외부로부터 인스턴스를 받아 i를 초기화(다형성)
this.i = i;
}
public void methodOfA(){
i.example(); // (5) 외부로부터 받아온 인스턴스의 메서드를 호출한다.
}
}
// (2) A가 사용하는 메서드를 가진 객체들이 I를 구현하도록 한다.
class B implements I {
@Override
public void example(){
...
}
}
class C implements I {
@Override
public void example(){
...
}
}
위에서는A는 자신이 사용할 객체를 스스로 생성하지 않고, 생성자를 통해 외부로부터 받아오고 있다. 즉, A는 자신이 사용할 객체를 알지 못하고, 그저 i에 할당된 인스턴스에 example()
이라는 메서드가 존재하는 것만 안다.
그렇다면 누군가 A가 사용할 객체를 결정하고 생성해서 A가 인스턴스화될 때 인자로 전달해주어야만 한다. 그래야 A는 B의 것이든, C의 것이든 example()
메서드를 호출할 수 있을 것이기 때문이다.
그 누군가가 바로 스프링이다. 스프링을 사용하면 애플리케이션의 로직 외부에서 A가 사용할 객체를 별도로 설정할 수 있습니다. 개발자가 설정 클래스 파일에 A가 사용할 객체를 C로 설정해두면, 애플리케이션이 동작하면서 스프링이 설정 클래스 파일을 해석하고, 개발자가 설정해둔대로 C 객체를 생성하여 A의 생성자의 인자로 C를 전달해준다.
이처럼 개발자가 아닌 스프링이 A가 사용할 객체를 생성하여 의존 관계를 맺어주는 것을 IoC(Inversion of Control, 제어의 역전)라고 하며, 그 과정에서 C를 A의 생성자를 통해 주입해주는 것을 DI(Dependency Injection, 의존성 주입)라고 한다.
AOP(Aspect Oriented Programming, 관심 지향 프로그래밍)
애플리케이션을 개발할 때에 구현해야 하는 기능들은 크게 공통 관심 사항과 핵심 관심 사항으로 분류할 수 있다.
이 때, 핵심 관심 사항과 공통 관심 사항이 코드에 같이 함께 모여 있으면 필연적으로 공통 관심 사항과 관련된 코드가 중복될 수밖에 없다. 이처럼 코드가 중복되어져 있는 경우, 공통 관심 사항을 수행하는 로직이 변경되면 모든 중복 코드를 찾아서 일일이 수정해주어야만 한다.
발생하는 코드의 중복이라는 문제를 해결하기 위해서는 공통 관심 사항과 관련된 기능들을 별도의 객체로 분리해낸 다음, 분리해낸 객체의 메서드를 통해 공통 관심 사항을 구현한 코드를 실행시킬 수 있도록 해야 한다. 이처럼, 애플리케이션 전반에 걸쳐 적용되는 공통 기능을 비즈니스 로직으로부터 분리해내는 것을 AOP(Aspect Oriented Programming, 관심 지향 프로그래밍)라고 합니다.
PSA(Portable Service Abstraction, 일관된 서비스 추상화)
스프링은 Java 백엔드 개발에 있어 핵심적인 역할을 수행하는 프레임워크이며, 백엔드 개발에서 데이터베이스는 떼어놓기 어렵다. 웹 서버는 데이터베이스와 소통하며 웹 클라이언트의 요청을 처리해야 하기 때문이다.
만약, 여러분이 MySQL을 사용하여 개발을 완료했는데, Maria DB로 데이터베이스를 바꿔야 하는 상황을 가정해보자. 각 데이터베이스 마다 사용 방법이 다르다면, 기존에 작성한 코드를 전부 지우고 새로 작성해야 하거나, 기존 데이터베이스와 새로운 데이터베이스 간에 사용 방법이 다른 코드를 모두 찾아서 일일이 수정해주어야 할 것이다.
그러나, 스프링을 사용하면 동일한 사용방법을 유지한 채로 데이터베이스를 바꿀 수 있다. 이는 스프링이 데이터베이스 서비스를 추상화한 인터페이스를 제공해주기 때문에 가능하다. 즉, 스프링은 Java를 사용하여 데이터베이스에 접근하는 방법을 규정한 인터페이스를 제공하고 있으며, 이를 JDBC(Java DataBase Connectivity)라고 합니다.
각 데이터베이스를 만든 회사들은 자신의 데이터베이스에 접근하는 드라이버를 Java 코드의 형태로 배포하는데, 이 드라이버에 해당하는 Java 코드의 클래스가 JDBC를 구현한다. JDBC를 기반으로 하여 데이터베이스 접근 코드를 작성해두면, 이후에 데이터베이스를 바꾸어도 기존에 작성한 데이터베이스 접근 로직을 그대로 사용할 수 있다.
이러한 JDBC처럼 특정 기술과 관련된 서비스를 추상화하여 일관된 방식으로 사용될 수 있도록 한 것을 PSA(Portable Service Abstraction, 일관된 서비스 추상화)라고 합니다.
MVC (Model Veiw Controller)
MVC란 Model View Controller 구조로 사용자 인터페이스와 비지니스 로직을 분리하여 개발 하는 것이다.
Spring의 MVC 구조를 살펴보면 아래와 같다.
View - Controller - Service - DAO - DTO
View 사용자에게 보여지는 화면을 View라고 한다. Spring에서는 JSP를 통해 화면을 구성하고 Controller를 통해 백엔드 서버와 연결한다.
Controller
View와 Service 사이를 연결한다. 클라이언트에서 입력한 URL에 맞는 View를 보여주고, View에서 처리하는 데이터를 Service로 전달해준다.
Service
실제 로직을 처리하는 곳으로 모든 기능은 Service에서 만들어진다. Controller를 통해 화면과 연결되고, DAO를 통해 데이터베이스와 연결된다.
DAO
Data Access Object의 줄임말. DAO는 프로젝트와 데이터베이스를 연결한다. Mapper에 SQL을 명시한뒤 Mapper와 함께 데이터베이스와 데이터를 주고받는다.
DTO
Data Transfer Object의 줄임말. DTO는 MVC 구조 사이사이에서 데이터 교환을 위한 오브젝트이다.
스프링의 장점
1. 모듈성과 확장성
스프링은 각 모듈이 독립적으로 사용될 수 있어 애플리케이션을 세분화하고 필요에 따라 확장하기 쉽게 만든다.
2. 테스트 용이성
의존성 주입을 통해 단위 테스트와 통합 테스트를 쉽게 수행할 수 있으며, 스프링의 테스트 지원 기능을 활용하여 테스트 코드 작성을 단순화할 수 있다.
3. 보안
스프링은 다양한 보안 기능을 제공하여 애플리케이션의 보안을 강화한다. 스프링 시큐리티(Spring Security) 모듈은 인증과 권한 관리를 쉽게 구현할 수 있도록 지원한다.
4. 커뮤니티와 생태계
스프링은 활발한 커뮤니티와 다양한 서드파티 라이브러리를 지원하는 풍부한 생태계를 가지고 있어 개발자들은 지속적인 지원과 업데이트를 받을 수 있다.
스프링의 주요 구성 모듈
1. Spring Core
Spring 프레임워크의 근간이 되는 DI(Dependency Injection) 기능을 지원하기 위한 핵심 모듈이다.
BeanFactory는 Inversion of Control (IoC) 패턴을 사용하여 빈 생성 및 빈의 의존 관계를 어플리케이션 코드에서 XML 설정 파일로 분리시킨다.
2. Spring Context
Spring Core 바로 위에 있으면서 Enterprise Application 개발이 용이하도록 국제화 메시지 처리, 애플리케이션 생명주기, 이벤트, 유효성 검증 등을 지원하는 모듈이다.
Java EE 기술(JNDI, Mail, JMS, EJB 등)과의 연동을 위한 Adapter들을 제공한다.
3. Spring DAO
JDBC 기반의 DAO 개발을 좀 더 쉽고, 일관된 방법으로 개발 가능하도록 지원하는 모듈이다.
DAO 추상 계층에서는 여러 데이터베이스 벤더들의 다양한 예외를 관리 할 수 있도록 중요한 예외 계층을 제공한다.
4. Spring ORM
- Object Relation Mapping Framework(iBatis, Hibernate, JDO 등)와의 연동을 지원하기 위한 모듈이다.
5. Spring AOP
Aspect Oriented Programming을 지원하기 위한 모듈이다.
Spring 프레임워크에서 관리되는 모든 객체에서 AOP가 가능하다.
6. Spring Web
웹 어플리케이션 개발에 필요한 실행환경을 제공하며, Multipart Request 등의 다양한 기능을 지원한다.
Struts2, JSF, Webwork 등 다양한 웹 어플리케이션 프레임워크와의 통합을 지원한다.
7. Spring MVC
MVC 웹 어플리케이션 개발을 지원하기 위한 모듈이다.
JSP, Velocity, Tiles 등 다양한 View 기술들을 사용하기 위한 API를 제공한다.
정리
- 스프링은 엔터프라이즈용 Java 애플리케이션 개발을 편하게 할 수 있게 해주는 오픈소스 경량급 애플리케이션 프레임워크다.
- 스프링은 POJO 프로그래밍을 지향하는 특징을 가지며, 그를 위해 IoC/DI, AOP, PSA를 지원한다.
- IoC는 객체 간의 의존 관계를 개발자가 아닌 스프링이 맺어주는 것을 의미한다.
- DI는 의존 객체를 특정 클래스에서 직접 생성하는 것이 아니라, 외부로부터 주입해주는 것을 의미한다.
- AOP는 애플리케이션 전반에 걸쳐 공통적으로 적용되는 코드들을 비즈니스 로직으로부터 분리해내는 것을 의미한다.
- PSA는 특정 기술과 관련된 서비스들을 추상화하여 일관된 방식으로 사용할 수 있도록 한 것을 의미한다.
- MVC는 Model View Controller 구조로 사용자 인터페이스와 비지니스 로직을 분리하여 개발 하는 것이다.