스프링이란?
스프링은 웹 개발에서 많이 사용하는 프레임워크로 웹 개발만을 위한 프레임워크라고 생각하기 쉬운데, 사실 스프링 프레임워크는 JAVA의 객체지향적 특성을 효과적으로 활용하도록 도와주는 프레임워크이다.
그럼 스프링은 어떤 방식을 사용하여 효과적으로 도와줄까? 그 방법에 대해 알아보자.
IoC / DI
스프링은 객체지향 프로그래밍을 돕기 위해 IoC와 DI라는 개념을 제공한다. IoC와 DI에 대해 하나씩 알아보자.
IoC (Inversion of Control / 제어의 역전)
1
Driver driver = new Driver();
일반적으로 프레임워크를 사용하지 않고 개발한다면 때 위의 코드처럼 객체를 직접 생성하고 그 객체의 생명주기(객체의 생성, 초기화, 사용, 소멸 등)를 개발자가 직접 관리한다.
하지만, 스프링 프레임워크를 사용한다면 생성하고 싶은 객체를 new
로 생성하는 대신 스프링 빈이라 불리는 무언가로 등록해주기만 한다면 스프링 프레임워크가 알아서 그 객체를 생성해준다. 그럼 개발자는 생성된 객체를 사용하기만 하면 된다.
이처럼 개발자가 직접 객체를 관리하지 않고 프레임워크가 관리하는 즉, 객체관리를 외부에 위임하는 방식을 IoC(제어의 역전)
이라 말한다.
이어서 스프링이 어떻게 IoC를 구현하는지 알아보자.
DI (Dependency Injection / 의존성 주입)
스프링은 DI(의존성 주입)
라는 방법을 사용해서 IoC를 구현한다. 여기서 의존성이란 뭘까?
한 객체에서 다른 객체를 사용하고 있을 때 의존하고 있다고 말한다.
1
2
3
4
public class Driver {
private Car car = new Car(); // Driver 객체가 Car 객체에 의존하고 있다.
// car 를 사용하는 메서드...
}
우리가 스프링 프레임워크를 사용하지 않는다면 Driver
에서 Car
를 사용하기 위해 new
로 생성해 사용한다. 그리고 이 방법은 의존성을 외부에서 주입받는 것이 아닌 내부에서 의존성을 생성하는 코드이다.
의존성을 외부에서 주입받는 코드를 보자.
1
2
3
4
5
6
7
public class Driver {
private Car car;
public Driver(Car car) { // 생성자를 통해 외부에서 Car 객체를 주입받아 사용한다.
this.car = car;
}
}
생성자를 통해 Driver
를 생성할 때 Driver
에서 사용할 Car
를 주입받게 된다면 Driver
는 내부에 새로 Car
를 생성하지 않고 외부에서 생성해 주입한 Car
를 사용할 수 있게 된다.
스프링은 위와 같은 DI를 사용해서 IoC를 구현한다.
객체를 스프링 빈으로 등록하여 객체의 생명주기 관리를 스프링 프레임워크에 위임하고(IoC), 위임한 객체를 개발자가 사용하기 위해 의존성 주입(DI)으로 객체를 주입받아 사용한다.
그래서 IoC와 DI가 객체지향에 도움이 되는이유는?
1
2
3
4
5
6
7
public class Suv extends Car {
...
}
public class Sedan extends Car {
...
}
Car
를 상속받는 여러 클래스들이 있다고 하자. 만약 의존성 주입을 사용하지 않는 상태에서 Car
를 Suv
나 Sedan
으로 바꿔야 한다면 어떻게 해야할까?
1
2
3
4
5
public class Driver {
private Car car = new Suv(); // Car대신 Suv로 변경.
// 만약 여기서 다시 Suv에서 Sedan으로 바꾼다면 다시 코드의 수정이 필요
// car 를 사용하는 메서드...
}
Driver 내부에서 new
로 생성하는 코드를 수정해야 한다. 하지만 의존성을 주입받는다면?
1
2
3
4
5
6
7
public class Driver {
private Car car;
public Driver(Car car) {
this.car = car;
}
}
1
2
3
4
5
6
public class Main {
public static void main(String[] args) {
Car car = new Suv();
Driver driver = new Driver(car);
}
}
주입받는 시점의 코드만 외부에서 수정하면 된다. 다시 말해, 내부의 코드 수정 없이 기능을 확장할 수 있는 것이다.
이처럼 의존 주입을 사용하게 된다면 추상화, 캡슐화, 상속, 다형성
같은 객체 지향의 특징을 잘 지킬 수 있으며 아래와 같은 객체 지향 설계를 만족할 수 있다.
내부 코드의 수정이 필요없이 새로운 기능을 추가할 수 있는
개방-폐쇄 원칙
을 지킬 수 있다.한 클래스는 하나의 책임만 가지기 때문에
단일 책임 원칙
을 지킬 수 있다.추상화에 의존하는
의존관계 역전 원칙
을 지킬 수 있다.
스프링은 이러한 객체지향의 특징과 설계를 만족하기 때문에 JAVA의 객체지향적 특성을 효과적으로 활용할 수 있도록 도와주는 프레임워크라고 하는 것이다.