작년에 참여했던 🦁 11기 강남대학교 멋쟁이사자처럼 백엔드 파트🦁 에서 SpringBoot 를 공부하게 되었고, 현재 백엔드 개발자를 희망하는 지금 저의 주력 프레임워크가 됐으나 한번 개념적인 내용을 집고 넘어가고 싶어 이 글을 시작으로 요약해보려고 합니다.
현재 이 포스팅에서는 다음과 같은 내용을 다뤄요
SpringBoot는 Spring 프레임워크의 단점을 보완하기 위해 나온 프레임 워크 입니다.
그렇다면 어떤 점이 나은지 알아야겠죠?
1. Spring의 설정의 복잡성
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=true&serverTimezone=Asia/Seoul"></property>
<property name="user" value="springstudent"></property>
<property name="password" value="springstudent"></property>
<property name="minPoolSize" value="5"></property>
<property name="maxPoolSize" value="20"></property>
<property name="maxIdleTime" value="30000"></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"></property>
<property name="packagesToScan" value="pe.pilseong.hibernateweb.entity"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
지금 보시는 xml 코드는 spring에서 Hibernate 를 사용하기 위해 작성하는 설정파일의 일부입니다.
지금은 객체 관계 매핑 프레임워크 하나라고 하지만 사용하는 모듈이 많아진다면....?
버전관리도 해야하고..... 환경 설정하는 것부터 맥이 빠져버릴겁니다.😭
이 상황을 대체하기 위해 SpringBoot는 spring-boot-stater 라는 Dependency를 추가하게 되면, 자주 사용하는 모듈들끼리 버전 호환까지 맞춰서 제공합니다.
많이 사용되는 spring-boot-starter 라이브러리를 간략하게 소개하자면,
2. SpringBoot 자동 설정
SpringBoot는 Spring의 기능을 사용하기 위한 자동설정(Auto Configuration)을 지원합니다.
여기서 말하는 자동설정이란 추가된 라이브러리를 실행하는데 필요한 환경 설정을 알아서 찾아준다 라는 말인데요,
다음은 SpringBoot 프로젝트를 생성하면 자동으로 생성되는 코드 입니다.
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(Test.class, args);
}
}
위에 @SpringBootApplication는 어노테이션(Annotation)이라고 불리는데 3개의 어노테이션이 합해진 어노테이션입니다.
만약 제가 작성한 코드로 SpringBootApplication을 실행시킬때, main 메서드가 돌아가는데 @SpringBootApplication안의 @ComponentScan이 @Component 시리즈의 어노테이션이 붙은 클래스들을 Spring Container 에 빈(Bean) 으로 등록합니다.
@Componet 시리즈는 다음과 같아요
- @Controller
- @RestController
- @Service
- @Repository
- @Configuration
이후 @EnableAutoConfiguration 어노테이션이 작동하여, spring-boot-autoconfigure 패키지 안에 spring.factories 파일 안에 있는 수많은 자동 설정들이 조건에 따라 적용됩니다.
3. SpringBoot 내장 WAS
앞서 말했던, spring-boot-starter-web 모듈의 경우 내장 톰캣(Tomcat)을 제공합니다. 때문에 Web 어플리케이션을 개발하기 위해 Spring을 사용할 때 했던 여러 번거로운 짓을 하지 않아도 된다는 것이죠!
여기까지 SpringBoot가 더 나은 점을 얘기했지만, 사실 SpringBoot는 Spring에서 나온 프레임워크이기에 Spring이 가지고 있는 장점 및 특징을 가지고 있어요.
이에 대해 밑에서 부터 기술됩니다.
제어의 역전이라고도 불리는데 단어 느낌만 봐도 먼가 주체가 아니다 라는 느낌이 나죠?
앞서 Spring vs SpringBoot에 대해 얘기할 때 SpringBoot 어플리케이션을 실행하고 메인 클래스가 실행될 때 @ComponentScan이 작동하여 @Component 시리즈의 class들을 Spring Container에 Bean으로 등록한다! 라고 얘기한 내용이 있어요.
이런식으로 말이죠!
그래서 Spring Container가 뭔데??🤔 라고 생각이 들어서 정리를 해봤습니다 :)
Spring Container 는 객체들의 생명주기를 관리합니다!
생명주기는 다음과 같은 단계를 거쳐요
- 객체 생성
- 의존성 주입
- 초기화
- 사용
- 소멸
코드로 한번 볼까요?
Myclass obj = new MyClass(); // 객체 생성
My Dependency dep = new MyDependency();
obj.setDependency(dep); // 의존성 주입
obj.init(); // 초기화
obj.eat(); // 사용
obj.close(); // 소멸
한 객체를 생성하고 의존성을 주입하려면 개발자가 직접 관리를 해야 합니다.
또한 new 생성자로 객체를 생성하고 class 간에 의존성을 높이게 되면 새로운 기능이 생겼을 때, 수작업으로 일일이 수정을 해야 하는 번거로운 상황이 발생합니다.
이를 해결 하기 위해 Spring Container에 Bean으로 등록하여 직접 관리 하게끔 한다. 라고 하여
제어의 역전이라고 합니다.
의존성 주입은 IoC에서 등록한 Bean을 class 에 주입하는 겁니다.
@RestController
public class TestController {
@Autowired
TestService testService;
}
이상한 점 못느끼셨나요?
@RestController
public class TestController {
TestService testService = new TestService();
}
원래라고 한다면 이렇게 객체를 선언 했겠지만 Spring에서는 IoC의 특징이 있기 때문에 개발자가 필요할 때마다 의존성을 Spring Container가 주입해주는 방식입니다.
이렇게 되면 class 간의 의존성이 느슨해지고 캡슐화를 높여 유지보수의 장점이 생겨요!
AOP는 관점을 기준으로 묶어 개발하는 방식을 말합니다.
어떤 기능을 구현할 때 핵심기능 과 부가기능 으로 구분해 각각을 하나의 관점으로 보는 것이죠.
예를 들어 볼까요?
클라이언트로부터 상품 정보 등록 요청을 받고 DB에 저장, DB에서 그 상품 조회
이 기능을 만들 때, (1) save(상품) (2)get(상품)이 기능의 핵심이죠?
만약 이 로직들 사이에 로깅 처리를 하는 기능을 추가적으로 넣어야 한다면 일반적인 OOP라면
이렇게 흘러가겠죠
하지만 여기서 공통적으로 사용되는 로깅 로직이 있다면?
반복되는 부가 기능을 하나의 공통 로직으로 처리하도록 모듈화해 삽입합니다.
이 방식을 AOP 라고 합니다.
SpringBoot는 Spring에서 나온 프레임워크이기에 IoC, AOP, DI의 특징을 공통적으로 가지고, 추가적으로 WAS, 의존성관리와 같은 좋은 기능들이 SpringBoot의 큰 장점인 것 같습니다.
아직 Auto-Configuration이나 Spring Container에 대한 내용이 좀 부족한 것 같아 직접 구현도 해보고 좀 더 깊게 공부하고 싶은 생각이 드네요..ㅎ