Spring(스프링)과 Spring Boot(스프링부트)를 왜 사용하는가?

Spring이 나오기 이전엔 ?

Java로 개발을 하던 초기에는 EJB(Enterprise Java Beans) 라는 기술을 사용했었습니다.

하지만 EJB는 이론적인 부분은 매력적이였지만 상당히 가격이 비쌌고, 복잡하고 어렵고 느리다는 단점이 있어

EJB로 개발하는 것은 지옥과 같다는 말이 나올 정도로 부정적인 말이 많았습니다.

그래서 차라리 EJB를 쓸 빠에는 POJO(Plain Old Java Object) 순수한 옛날 자바로 돌아가자라는 말이 나오기도 했었습니다.

그러다 EJB에 지친 개발자들이 오픈소스 프로젝트로 Spring이라는 오픈소스 기술을 개발하였고

이 Spring은 EJB의 복잡하고 어렵고 느리고 비싼 단점들을 개선하고 수 많은 편의기능들을 제공하여

Spring이라는 이름"EJB라는 겨울을 넘어 새로운 시작 봄이 왔다"라는 뜻을 갖고 있다고 합니다.

 


Spring(스프링)

스프링은 Java로 애플리케이션을 만들기 위한 Java의 웹 프레임워크로 Java언어를 기반으로 사용합니다.

자바 언어 기반의 프레임 워크이기 때문에 자바가 가진 객체 지향 언어라는 강력한 특징을 살려내기 때문에

Spring은 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임 워크이라고 할 수 있습니다.

 

스프링은 특히 객체 지향의 개념에 필요한 다형성을 극대화해서 이용할 수 있게 도와 줍니다.

스프링이 제공하는 IoC(제어의 역전), DI(의존관계 주입)다형성을 활용해 역할과 구현을 편리하게 다룰 수 있도록 지원 해줍니다.

그래서 스프링을 사용하면 마치 레고 블럭을 조립하듯이 구현을 편리하게 유연하게 변경할 수 있습니다.

아래의 스프링 프레임 워크의 특징들을 살펴 봅시다.

 

스프링 프레임 워크의 특징

📌 1. IoC(제어의 역전)

Java로 개발시 new 연산자, 인터페이스 호출 등으로 객체를 생성 또는 소멸 시킵니다.

여기서 IoC란 객체의 생성부터 소멸까지 개발자가 아닌 스프링 컨테이너가 대신 해주는 것입니다.

즉, 제어권이 개발자가 아닌 IoC에 있으며, IoC가 개발자의 코드를 호출해 필요한 객체를 생성 또는 소멸하며 생명주기를 관리해줍니다.

스프링 컨테이너에 등록된 객체는 기본적으로 Singleton(싱글톤)으로 관리 됩니다.

 

스프링 컨테이너에 객체를 등록하기 위해서는 두 가지 방법이 있습니다.

Component Scan 방식

@Conponent를 포함하는 @Controller, @Service, @Repository 와 같은 어노테이션을 클래스에 붙여 컴포넌트 등록이 가능합니다.

위 코드는 MemberController를 @Controller로 Bean을 등록하고

@Autowired 어노테이션을 MemberService를 매개변수로 받은 MemberController 생성자에 붙여

MemberController와 MemberService를 서로 연결하였습니다.

 

스프링 빈 직접 등록

@Configuration@Bean 어노테이션으로 직접 코드를 작성해 등록이 가능합니다.

@Bean은 메서드 위에 붙여 사용하며 메서드 이름이 곧 Bean의 이름이 됩니다.

 

 

위 두 그림에 사용된 @Autowired ??

필요한 의존 객체의 “타입"에 해당하는 빈을 찾아 주입합니다.

@Autowired는 두 객체의 의존 관계를 서로 연결할 때 사용합니다.

( 생성자, Setter, 필드 )에 @Autowired를 붙여 의존성을 주입, 연결할 수 있습니다.


📌 2. DI(의존 관계 주입)

만약 아래와 같이 MemberService가 MySQLRepository를 사용한다고 가정해 봅시다.

이때 MemberService는 MySQLRepository를 의존하며 사용하고자 하는 DB가 JPA로 변경 될 경우 MemberService에 영향을 미치게 됩니다.

그렇게 된다면 MemberService의 생성자를 JPARepository로 변경해야 하고 또 변경이 필요할 경우 매번 생성자를 바꿔야 하는 등 유연성이 떨어지게 됩니다.

 

또한 객체 지향 5원칙인 "SOLID" 중 DIP인 "추상화(인터페이스)에 의존해야지, 구체화(구현 클래스에)에 의존하면 안된다."이 있습니다.

여기서는 MySQLRepository는 인터페이스가 아닌 클래스이므로  MemberService가 구체화에 의존하므로 DIP를 위반하게 됩니다.

 

이때 이러한 문제점을 해결 할 수 잇는 것이 바로 DI(의존 관계 주입)입니다.

DI는 의존 관계를 외부에서 결정(주입)해주는 것을 말합니다.

스프링에서는 이러한 DI를 담당하는 DI 컨테이너가 존재하며, 이 DI 컨테이너가 객체들 간의 의존 관계를 주입해줍니다.

 

위 문제점을 DI를 이용해 코드를 수정하면 MemberRepository라는 인터페이스를 만들고, 이후 사용할 DB저장소들은 이 MemberRepository를 구현하는 식의 방식을 사용합니다.

이렇게 되면 사용하는 DB가 변경될 경우 아래처럼 생성자를 변경하지 않고 그 시점에 필요한 객체를 생성해 MemberService에 주입해주면 됩니다.

// MySQLRepository를 사용할 경우 
MemberService memberService = new MemberService(new MySQLRepository());

// JpaRepository를 사용할 경우
MemberService memberService = new MemberService(new JpaRepository());

 

이처럼 DI를 이용하면, 그 때 그 때 상황마다 필요한 부분을 뺐다 꼈다 하면서 적절한 상황에 필요한 기능 유연하게 변경할 수 있습니다.

 

DI에 대한 자세한 설명은 아래 포스팅에서 다룹니다.

 

[Java] 의존성 주입(DI)이란? (OCP와 DIP를 지키기 위한 방법)

SOLID 원칙 중에서 OCP와 DIP에 대해 많이 들어봤을 것이다. OCP와 DIP를 모르는 사람을 위해 간단히 설명해보자면 OCP (Open Closed Principle) - 개방 폐쇠 원칙 변경에는 닫혀 있고, 확장에는 열려 있어야

hstory0208.tistory.com


📌 3. AOP(관점 지향 프로그래밍)

로깅, 트랜잭션, 보안 등 여러 모듈에서 공통적으로 사용하는 기능을 분리하여 관리 할 수 있습니다.

각각의 클래스들에 서로 코드와 기능들이 중복되는 부분이 많다면 유지 보수가 상당히 어려울 것입니다.

중복된 코드를 최대한 배제하는 방법은 중복되는 기능들을 전부 빼놓은 뒤 그 기능이 필요할때만 호출하여 쓰면 훨씬 효율적입니다.

AOP여러 객체에 공통으로 적용할 수 있는 기능을 구분함으로써 재사용성을 높여주는 프로그래밍 기법으로 스프링에서 다음과 같이 사용할 수 있습니다.

위 코드는 com.example.hellospring 패키지 하위에 있는 모든 클래스들에 메서드 작동 시간을 적용한 코드 입니다. 


📌 4. POJO(Plain Old Java Object) 방식

POJO는 다른 클래스나 인터페이스를 상속/implements 받아 메서드가 추가된 클래스가 아닌 일반적으로 우리가 알고 있는 getter, setter 같이 기본적인 기능만 가진 자바 객체를 말합니다.

EJB를 사용할 당시에는 가벼운 서비스 조차 무겁게 만들어 졌고, 다른 기능으로 대체하기 위해선 전체 코드를 수정해야하는 문제점들이 발생해 많은 어려움이 있었습니다.

그래서, Java의 기본 개념인 객체 지향에 집중하고 특정 클래스나 라이브러리에 족송되지 않는 POJO 구성으로 코드를 작성해 이러한 문제점을 해결하고자 POJO기반의 구성을 이루게 되었습니다.

 


Spring Boot (스프링 부트)

스프링 부트는 "스프링을 편리하게 사용할 수 있도록 지원"해주는 기술 입니다.

Spring Boot를 이용함으로써 다음과 같은 편리함을 얻을 수 있습니다.

 

 

Spring Boot의 장점

📌 1. Tomcat을 내장해서 별도의 웹 서버를 설치하지 않아도 된다.

스프링 부트는 WAS인 Tomcat을 내장

@SpringBootApplication 어노테이션이 선언되어 잇는 클래스의 main() 메소드를 실행하는 것만으로 서버를 구동 시킬 수 있습니다.

내장 톰캣을 사용하기 위해서는 별도 설치 없이 build.gradle 아래 의존성을 추가해주기만 하면 됩니다.

'org.springframework.boot:spring-boot-starter-web'

📌 2. 독릭접으로 실행 가능한 JAR

웹 애플리케이션을 배포하기 위해서는 .war 파일로 패키징해 배포해야했지만,

스프링 부트는 내장 Tomcat을 지원하기 때문에 웹 애플리케이션을 .jar 파일로 패키징해 웹 애플리케이션을 실행시킬 수 있습니다.

 


📌 3. 손쉬운 빌드 구성을 위한 starter 종속성 제공

build.gradle에 필요한 라이브러리를 추가하면 필요한 나머지 라이브러리도 묶음으로 같이 받아와 줍니다.

 


📌 4. 라이브러리 버전 자동관리

기존 스프링 라이브러리는 버전을 직접 입력해야했지만, 스프링 부트는 build.gradle에 스프링 부트 버전을 입력해 놓으면

spring 라이브러리 뿐만 아니라 third party라이브러리들도 호환되는 버전을 알아서 다운로드 및 관리 해줍니다.

 


📌 5. 관례에 의한 간결한 설정

Spring만을 사용할 때는 설정이 정말 힘들었지만

Spring Boot는 웬만한 설정이 Default로 되어 있고, 필요한 설정은 메뉴얼에 나와있어 필요하다면 설정을 커스텀하게 바꿀 수 있습니다.