*강경미 | 웹 백엔드 강의를 참조한 글입니다.
다른 강의에서도 스프링 프레임워크에 대해 다루긴 했으나, 예제를 통해 중간중간 개념을 배우는 형식이었기에 정보들이 분산되어 정리되어있었다. 이 카테고리에서 다루고 있는 강의에서는 개념과 실습이 분리되어 있어, 초심자가 공부하기에는 더 적절할 듯 하다.
1. 객체 지향과 스프링 [김영한 | 스프링 핵심 원리 - 기본편]
김영한 | 스프링 핵심 원리 - 기본편을 참조한 글입니다. 1. 스프링이 태어났어요 스프링이 탄생하기 전 2000년대 초반에는, EJB(Enterprise Java Beans)를 사용했다. EJB에는 이론이 어렵고 복잡하며, 값이
8w8u8.tistory.com
1. Spring Framework란?
스프링 프레임워크를 설명하기에 앞서, 프레임워크는 무엇인가?
내가 원목 서랍을 만들고자 할 때, 목재를 사와서 재단하는 일부터 시작할 수도 있다.
정말 특수한 형태라면 목재를 직접 재단하고 만들어야하겠지만
그렇지 않은 경우라면 이미 잘 만들어져있는 반제품을 사용해 시간과 노력을 절약할 수 있다.
반제품에서 시작하여 추가적으로 내가 원하는 부분을 넣고, 물감을 이용해 색칠하면 비교적 빠르고 쉽게 서랍이 완성된다.
이런 반제품의 역할을 하는 틀이 프레임워크이고, 스프링은 많은 프레임워크들 중 하나이다.
*프레임워크와 라이브러리의 차이
프레임워크는 원하는 기능 구현에 집중하여 개발할 수 있는 뼈대이자 틀을 제공한다.
- Spring : Java 서버 개발에 사용
- Django, Flas : Python 서버 개발에 사용
- Android : 안드로이드 앱 개발에 사용
- Cocoa Touch : 아이폰 앱 개발에 사용
- Angular, Vue.js : 웹 개발에 사용
- Express.js : Node.js의 대표적인 프레임워크
라이브러리는 소프트웨어를 개발할 때 사용하는 기능을 구현하기 위한 코드를 모아둔 집합이다.
- STL : C++의 표준 템플릿 라이브러리
- Jquery : HTML의 클라이언트 사이드 조작을 단순화
- React.js : 웹에서 사용자 인터페이스 개발에 사용 (홈페이지에서 프레임워크가 아닌 라이브러리라고 명시해둠)
프레임워크와 라이브러리의 결정적 차이점은 제어의 권한이 누구에게 있는지이다.
프레임워크는 프레임워크가 제어 흐름 권한을 가지고 있다. 애플리케이션 코드가 프레임워크가 짜 놓은 틀 속에서 수동적으로 동작하기 때문이다. 즉, 제어의 역전(IoC)이 이루어졌다.
반면, 라이브러리의 경우 사용자(개발자)가 제어 흐름 권한을 가진다. 개발시 필요한 기능이 있으면 라이브러리를 호출하여 사용하는 능동적인 모습을 보여준다.
Spring Framework란?
- 엔터프라이즈급(큰 규모의) 어플리케이션을 구축할 수 있는 가벼운 솔루션
- 원스-스탑-숍(One-Stop-Shop; 모든 과정을 한 번에 해결 가능)
- 원하는 부분만 가져다 사용할 수 있도록 모듈화가 잘 되어 있다.
- IoC 컨테이너(=스프링 컨테이너)이다 => 인스턴스 생성부터 소멸까지의 인스턴트 생명주기 관리를 개발자가 아닌 컨테이너가 해준다. 객체관리 주체가 컨테이너이기에 개발자는 로직에 집중할 수 있다.
- 선언적으로 트랜잭션을 관리한다.
- 완전한 기능을 갖춘 MVC Framework를 제공한다.
- AOP(Aspect Oriented Programming; 관점 지향 프로그래밍) 지원 => 어떤 로직을 기준으로 핵심/부가적인 관점으로 나누고 그 관점을 기준으로 각각 모듈화한다.
- 스프링은 도메인 논리 코드와 쉽게 분리될 수 있는 구조이다.
*모듈화 : 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것
스프링의 장점은 모듈화인만큼, 스프링 코어(핵심기술)만 알고 나머지 기능들은 필요할 때 하나씩 공부하면서 사용해도 괜찮다.
2. IoC 컨테이너
2-1. 컨테이너(Container)란?
- 인스턴스의 생명주기를 관리
- 생성된 인스턴스에게 추가적인 기능 제공
예를 들어, Servlet을 실행해주는 WAS는 Servlet 컨테이너를 가지고 있다고 말한다.
WAS는 웹 브라우저로부터 서블릿 URL에 해당하는 요청을 받으면, 서블릿을 메모리에 올린 후 실행한다.
개발자가 서블릿 클래스를 작성했지만, 실제로 메모리에 올리고 실행하는 것은 WAS가 가지고 있는 Servlet 컨테이너이다. Servlet컨테이너는 동일한 서블릿에 해당하는 요청을 받으면, 또 메모리에 올리지 않고 기존에 메모리에 올라간 서블릿을 실행하여 그 결과를 웹 브라우저에게 전달한다.
2-2. IoC란?
- IoC = Inversion of Controller ; 제어의 역전
- 개발자는 프로그램의 흐름을 제어하는 코드를 작성한다. 그런데, 이 흐름의 제어를 개발자가 하는 것이 아니라 다른 프로그램이 제어하는 것을 IoC라고 말한다.
예를 들어, 서블릿 클래스는 개발자가 만들지만, 그 서블릿의 메소드를 알맞게 호출하는 것은 WAS이다.
이렇게 개발자가 만든 어떤 클래스나 메소드를 다른 프로그램이 대신 실행해주는 것이 IoC이다.
3. DI
- DI = Dependency Injection ; 의존성 주입
- 외부에서 객체를 주입받는 것을 DI라고 한다.
- 즉, 개발자가 new를 통해 객체를 직접 생성하는 것이 아니라 @xxxx 애노테이션을 붙여줌으로써 DI받는 것
- 스프링 컨테이너에서 객체가 관리되다가(스프링 컨테이너가 관리하는 객체를 빈;bean이라고 부른다), 필요할 때 객체를 주입한다.
4. Spring에서 제공하는 IoC/DI 컨테이너
지금까지 개발자를 대신하여 스프링이 객체를 만들고, 제어하는 방법에 대해 배웠다.
그렇다면 스프링이 객체를 만드는 곳(=객체 공장이라고 볼 수 있다)은 무엇일까?
대표적으로 BeanFactory, ApplicationContext가 있다.
- BeanFactory : IoC/DI에 대한 기본 기능을 가지고 있다.
- ApplicationContext : BeanFactory의 모든 기능을 포함하며, 더 복잡한 기능을 수행할 수 있어 일반적으로 BeanFactory보다 추천된다. 트랜잭션처리, AOP등에 대한 처리를 할 수 있다. BeanPostProcessor, BeanFactoryPostProcessor등을 자동으로 등록하고, 국제화 처리, 어플리케이션 이벤트 등을 처리할 수 있다.
- BeanPostProcessor : 컨테이너의 기본로직을 오버라이딩하여 인스턴스화, 의존성 처리 로직 등을 개발자가 원하는 대로 구현 할 수 있도록 한다.
- BeanFactoryPostProcessor : 설정된 메타 데이터를 커스터마이징 할 수 있다.
5. Bean - Java Bean 과 Spring Bean
5-1. Bean Class란?
- Bean은 Java Bean과 Spring Bean으로 나뉜다.
- Java Bean이란 비주얼 툴에서 조작 가능한 컴포넌트를 말하며, 비주얼 컴포넌트 환경에서 웹 기반의 엔터프라이즈 환경으로 바뀌며 잘 사용하지 않는다.
- Java Bean의 세 가지 특징
- (파라미터가 없는) 기본생성자를 가지고 있다.
- 툴이나 프레임워크에서 리플렉션을 통해 객체를 생성하기 때문이다.
- 만약 파라미터가 존재하는 생성자를 추가한 경우에는 기본 생성자 코드를 작성하지 않으면 기본 생성자가 없는 상황이 되므로 주의해야 한다.
- 필드는 private하게 선언한다.
- getter, setter 메소드를 가진다.
- (파라미터가 없는) 기본생성자를 가지고 있다.
*기본 생성자
: 생성자란, 속성과 동작을 가진 하나의 완성된 값으로 new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당한다.
기본 생성자란, 클래스에 아무런 생성자를 만들지 않았을 때 자동으로 생성되는 생성자이다.
public class Member {
private Long id;
private String name;
}
다음과 같이 Member 클래스를 만들었다면, 자동으로 아래의 기본 생성자가 생긴다.
Mamber() {
}
보다시피, 파라미터가 없는 빈 상태의 기본 생성자이다.
기본 생성자를 없애려면 사용자 정의 생성자를 만들면 된다.
public class Member {
private Long id;
private String name;
Member(Long id, String name) {
this.id = id;
this.name = name;
}
}
*리플렉션
: 구체적인 클래스 타입을 알지 못해도 그 클래스의 정보(메서드, 타입, 변수 등)에 접근할 수 있게 해주는 자바 API
*기본 생성자가 필요한 이유
기본 생성자를 사용하지 않는 경우라도 기본 생성자를 없애면 에러가 발생한다.
자바 리플렉션을 이용하면 로딩이 완료된 클래스에서 다른 클래스를 동적으로 로딩하여 해당 클래스의 정보를 알 수 있다. 그러나 리플렉션도 가져올 수 없는 정보가 있는데, 바로 생성자의 인자 정보들이다. 그래서 기본 생성자 없이 파라미터가 있는 생성자만 존재한다면, 자바 리플렉션이 객체를 생성할 수가 없다.
*Member라는 클래스가 name라는 필드를 가지고 있다면 이 필드의 getter setter 메서드는 getName(), setName()이 될 것이다. getName(), setName() 메서드를 가리켜서 name 프로퍼티(property)라고 한다.
- Spring Bean란 스프링(컨테이너)에 의해서 생성되고 관리되는 자바 객체를 말한다.(이 글의 3번에서 DI를 공부할 때 나온 개념)
5-2. Java Config
의존성 주입을 위한 스프링 빈을 등록하는 방법에는 두 가지가 있다.
1. 컴포넌트 스캔과 자동 의존관계 설정
: 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다.
2. 자바 코드로 직접 스프링 빈 등록하기
: 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야하는 경우 스프링 빈으로 등록한다.
그중 자바 코드로 직접 스프링 빈을 등록하는 방법에는 xml을 이용한 설정과 Java Config를 이용한 설정이 있다.
Java Config란 말 그대로 자바 클래스 파일을 설정 파일로 사용하겠단 것이다.
xml 설정과 비교해서 Java Config는 이클립스나 인텔리J와 같은 IDE에서 오타를 발견하기 쉽고, 자동완성을 지원하기 때문에 더욱 편리하다. 그래서 최근에는 xml 설정을 잘 사용하지 않는다.
5-2-1. 애노테이션
애노테이션은 jdk 5부터 지원된다.
사전적인 의미는 '주석'이란 뜻이지만, 자바 애노테이션은 특수한 의미를 부여하는 역할을 수행한다.
특수한 의미란 컴파일 또는 런타임 할 때 해석이 될 수 있으며, 스프링은 다양한 애노테이션을 제공한다.
@Configuration
- Java Config 로 설정을 할 클래스 제일 위에 @Configuration 을 붙여준다.
- 스프링 설정 클래스를 선언하는 애노테이션
- 이건 설정파일이야 ~ / Bean 등록할거야 ~ 란 의미이다.
- AnnotationContext 중에서 AnnotationConfigApplicationContext는 Java Config 클래스를 읽어들여 IoC와 DI를 적용한다.
@Bean
- bean을 정의하는 애노테이션
- Java Config 설정 파일 중에 @Bean이 붙어 있는 메서드들을 AnnotationConfigApplicationContext는 자동으로 실행하여 그 결과로 리턴하는 객체들을 기본적으로 싱글톤(메모리에 하나만 생성)으로 관리를 하게 된다.
@ComponentScan
- @Controller, @Service, @Repository, @Component 애노테이션이 붙은 클래스를 찾아 컨테이너에 등록
@Component
- 컴포넌트 스캔의 대상이 되는 애노테이션 중 하나로써 주로 유틸, 기타 지원 클래스에 붙이는 애노테이션
@Autowired
- 주입 대상이되는 bean을 컨테이너에 찾아 주입하는 애노테이션
이번 글에서 배운 내용 - 의존관계 주입을 위한 스프링 빈 등록 방법 - 을 활용한 예제를 여기에서 확인할 수 있다.
'back-end > 강경미 | 웹 백엔드' 카테고리의 다른 글
1. DBMS란? / SQL 설치 및 실행 (0) | 2023.02.20 |
---|