스프링이란 무엇인가?
스프링은 자바 엔터프라이즈 애플리케이션 개발에 사용되는 애플리케이션 프레임워크
- 애플리케이션의 기본 틀 - 스프링 컨테이너
스프링 컨테이너는 설정정보를 참고로 해서 애플리케이션을 구성하는 오브젝트를 생성하고 관리한다.
- 공통 프로그래밍 모델 - IoC/DI, 서비스 추상화, AOP
1. IOC/DI 모델
2. 서비스 추상화
3. AOP
- 기술 API
스프링은 엔터프라이즈 애플리케이션을 개발의 다양한 영역에 바로 활용할 수 있는 방대한 양의 기술 API를 제공한다.
스프링의 성공요인
- 단순함
가장 단순한 객체지향적인 개발 모델인 POJO 프로그래밍 강력 주장
- 유연성
스프링의 유연성으로 인해 다른 많은 프레임워크와 편리하게 접목돼서 사용할 수 있으며 유연성과 확장성이 매우 뛰어나다.
1.1 초난감 DAO
간단한 유저 정보를 저장하는 DAO, Connection을 분리하지 않아서 연결 방법이 변경되면 수많은 코드를 수정해야 한다.
관심사의 분리가 필요하다.
1.2.2 커넥션 만들기의 추출
- UserDao의 관심사항
현재 DB 커넥션을 가져오는 코드는 다른 관심사와 섞여서 같은 add() 메소드에 담겨 있다. 이렇게 하나의 관심사가 방만하게 중복되어 있고, 여기저기 흩어져 있어서 다른 관심의 대상과 얽혀 있으면, 변경이 일어날 때 엄청난 고통을 일으키는 원인이 된다.
- 중복 코드의 메소드 추출
커넥션을 가져오는 중복 코드를 분리하자.
중복된 DB 연결 코드를 getConnection()이라는 이름의 독립적인 메소드로 만들어주자.
앞으로 DB 연결 코드가 변경되어도 getConnection()이라는 한 메소드의 코드만 수정하면 된다.
private Connection getConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection c = DriverManager.getConnection(...);
return c;
}
1.2.3 DB 커넥션 만들기의 독립
- 상속을 통한 확장
추상 클래스와 상속 클래스로 클래스 계층 구조를 분리하자.
슈퍼클래스에 기본적인 로직의 흐름(커넥션 가져오기, SQL 생성, 실행, 반환)을 만들고, 그 기능의 일부를 추상 메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤 서브클래스에서 이런 메소드를 필요에 맞게 구현해서 사용하도록 하는 방법을 사용하자. (템플릿 메소드 패턴)
UserDao에 팩토리 메소드 패턴을 적용해서 getConnection()을 분리하자.
1.3 DAO의 확장
여러가지 단점이 많은 상속을 이용하지 않고 DAO를 확장하는 방법은 없을까?
1.3.1 클래스의 분리
Connection을 반환하는 makeNewConnection() 메서드를 가지는 SimpleconnectionMaker 클래스를 분리하자.
이렇게 하면 상속은 하지 않지만 클래스에 종속성이 생기고 변경이 생기면 복잡해진다.
1.3.2 인터페이스의 도입
두 개의 클래스가 서로 긴밀하게 연결되어 있지 않도록 중간에 추상적인 느슨한 연결고리를 만들어주자. (인터페이스)
UserDao는 인터페이스의 메서드를 통해 알 수 있는 기능에만 관심을 가지면 되지, 그 기능을 어떻게 구현했는지에는 관심을 둘 필요가 없어진다.
하지만 여전히 connectionMaker = new DConnectionMaker()와 같이 초기에 한 번 어떤 클래스의 오브젝트를 사용할지를 결정하는 생성자의 코드가 남아있다.
1.3.3 관계설정 책임의 분리
관심을 분리해서 클라이언트에게 떠넘겨보자.
ConnectionMaker connectionMaker = new DConnectionMaker();
UserDao dao = new UserDao(connectionaker);
클라이언트에서 DConnectionMaker를 생성하고 UserDao 생성자에 주입하여 UserDao를 생성한다.
앞에서 사용했던 상속을 통한 확장 방법보다 더 깔끔하고 유연항 방법으로 클래스 분리, 확장에 용이한 구조가 되었다.
1.3.4 원칙과 패턴
- 개방 폐쇄 원칙
클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.
- 높은 응집도와 낮은 결합도
1. 응집도가 높다는 건 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중되어 있다는 뜻이다.
2. 하나의 오브젝트가 변경이 일어날 때에 관계를 맺고 있는 다른 오브젝트에게 변화를 요구하는 정도
- 전략 패턴
자신의 기능 맥락에서 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴이다.
1.4 제어의 역전(IoC)
1.4.1 오브젝트 팩토리
- 팩토리
객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 ㄹ돌려준다. 이런 일을 하는 오브젝트를 흔히 팩토리라고 부른다. 추상 팩토리 패턴이나 팩토리 메소드 패턴과는 다르니 혼동하지 말자.
public class DaoFactory{
public UserDao userDao(){
ConnectionMaker connectionMaker = new DConnectionMaker();
UserDao userDao = new UserDao(ConnectionMaker);
return userDao;
}
}
1.4.2 오브젝트 팩토리의 활용
DAO 생성 메소드의 추가로 인해 발생하는 중복을 제거하자.
1.4.3 제어권의 이전을 통한 제어관계 역전
- 제어의 역전이란?
간단히 프로그램의 제어 흐름 구조가 뒤바뀌는 것이라고 설명할 수 있다.
- 일반적인 제어의 흐름
1. 메소드와 같이 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정
2. 결정한 오브젝트를 생성
3. 만들어진 오브젝트에 있는 메소드 호출
4. 그 오브젝트 메소드 안에서 다음에 사용할 것을 결정하고 호출
5. 반복
- 제어의 역전
일반적인 제어 흐름 개념을 거꾸로 뒤집는 것.
오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않고 어떻게 만들어지고 어디서 사용되는지를 알 수 없다. 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 때문이다.
1.5 스프링의 IoC
1.5.1 오브젝트 팩토리를 이용한 스프링 IoC
- 애플리케이션 컨텍스트와 설정정보
스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 빈(bean)이라고 한다.
빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트를 빈 팩토리라고 부른다.
보통 빈 팩토리보다는 이를 좀 더 확장한 애플리케이션 컨텍스트를 주로 사용한다.
- DaoFactory를 사용하는 애플리케이션 컨텍스트
자바 코드의 탈을 쓰고 있지만, 사실은 XML과 같은 스프링 전용 설정정보
@Configuration // 애플리케이션 컨텍스트 또는 빈 팩토리가 사용할 설정정보라는 표시
public class DaoFactory {
@Bean // 오브젝트 생성을 담당하는 IoC용 메소드라는 표시
public UserDao userDao() {
return new UserDao(connectionMaker());
}
@Bean
public ConnectionMaker connectionMaker() {
return new DConnectionMaker();
}
}
1.5.2 애플리케이션 컨텍스트의 동작방식
애플리케이션 컨텍스트가 DaoFactiory의 userDao() 메서드를 호출해서 오브젝트를 가져온 것을 클라이언트가 getBean()으로 요청할 때 전달해준다.
- 애플리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점
1. 클라이언트는 구체적인 패곹리 클래스를 알 필요가 없다.
2. 애플리케이션 컨텍스트는 종합 IoC 서비스를 제공해준다.
3. 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다.
1.5.3 스프링 IoC의 용어 정리
- 빈(bean)
빈 또는 빈 오브젝트는 스프링이 IoC 방식으로 관리하는 오브젝트라는 뜻이다. 관리되는 오브젝트라고 부르기도 한다.
- 빈 팩토리(bean factory)
스프링의 IoC를 담당하는 핵심 컨테이너를 가리킨다. 빈을 등록하고, 생성하고, 조회하고 돌려주고, 그 외에 부가적인 빈을 관리하는 기능을 담당한다.
- 애플리케이션 컨텍스트(application context)
빈 팩토리를 확장한 IoC 컨테이너, 빈을 등록하고 관리하는 기본적인 기능은 빈 팩토리와 동일하다. 여기에 스프링이 제공하는 각종 부가 서비스를 추가로 제공한다.
- 설정정보/설정 메타 정보
스프링의 설정정보란 애플리케이션 컨텍스트 또는 빈 팩토리가 IoC를 적용하기 위해 사용하는 메타정보를 말한다.
-컨테이너 또는 IoC 컨테이너
IoC 방식으로 빈을 관리한다는 의미에서 애플리케이션 컨텍스트나 빈 팩토리를 컨테이너 또는 IoC 컨테이너라고 부른다.
1.6 싱글톤 레지스트리와 오브젝트 스코프
1.6.1 싱글톤 레지스트리로서의 애플리케이션 컨텍스트
애플리케이션 컨텍스트는 우리가 만들었던 오브젝트 팩토리와 비슷한 방식으로 동작하는 IoC 컨테이너이다. 그러면서 동시에 이 애플리케이션 컨텍스트는 싱글톤을 저장하고 관리하는 싱글톤 레지스트리이기도 하다.
스프링은 별다른 설정을 하지 않으면 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 만든다.
- 서버 애플리케이션과 싱글톤
왜 스프링은 싱글톤으로 빈을 만드는가?
이는 스프링이 주로 적용되는 대상이 자바 엔터프라이즈 기술을 사용하는 서버환경이기 때문이다.
매번 요청이 올때마다 오브젝트를 새로 생성하면 서버가 감당하기 어렵기 때문이다.
- 자바 싱글톤 패턴의 한계
1. private 생성자를 갖고 있기 때문에 상속할 수 없다.
2. 싱글톤은 테스트하기 힘들다.
3. 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
4. 싱글톤의 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못하다.
- 싱글톤 레지스트리
자바의 기본적인 싱글톤 패턴의 구현 방식은 여러 가지 단점이 있기 때문에 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공한다. 그것이 바로 싱글톤 레지스트리다.
1.6.2 싱글톤과 오브젝트의 상태
읽기전용의 속성을 가진 정보라면 싱글톤에서 인스턴스 변수로 사용하자. 개별적으로 바뀌는 정보는 로컬 변수로 정의하거나, 파라미터로 주고받으면서 사용하자.
1.6.3 스프링 빈의 스코프
빈이 생성되고 존재하고, 적용되는 범위 = 스코프
스프링 빈의 기본 스코프는 싱글톤이다.
1.7 의존관계 주입(DI)
1.7.1 제어의 역전(IoC)과 의존관계 주입
IoC 컨테이너 = DI 컨테이너 = 스프링
1.7.2 런타임 의존관계 설정
- 의존관계
B가 변하면 A에 영향을 미친다.
- UserDao의 의존관계
인터페이스를 통해서 의존관계를 제한해주면 그만큼 변경에서 자유로워진다.
1.7.3 의존관계 검색과 주입
런타임 시에 의존관계를 결정한다는 점에서 의존관계 주입과 비슷하지만 의존관계를 맺는 방법이 외부로부터의 주입이 아니라 스스로 검색을 이용하기 때문에 의존관계 검색이라고 불리는 것도 있다.
- 의존관계 검색 vs 주입
의존관계 주입 쪽이 훨씬 단순하고 깔끔하다.
1.7.4 의존관계 주입의 응용
- 기능 구현의 교환
//개발용
@Bean
public ConnectionMaker connectionMaker(){
return new LocalDBConnectionMaker();
}
//운영용
@Bean
public ConnectionMaker connectionMaker(){
return new ProductionDBConnectionMaker();
}
1.7.5 메소드를 이용한 의존관계 주입
- 수정자 메소드를 이용한 주입
- 일반 메서드를 이용한 주입
1.8 XML을 이용한 설정
XML을 이용해서 DI의 설정정보 만드는 방법
'Spring-Boot' 카테고리의 다른 글
토비의 스프링 3.1 Vol.1 250p ~ 350p 정리 (1) | 2023.12.30 |
---|---|
토비의 스프링 3.1 Vol.1 145p ~ 250p 정리 (1) | 2023.12.28 |
실시간 시세 시스템아키텍처에 대한 고민, feat.토스증권 (0) | 2023.10.14 |
Spring-Boot + redis + kafka로 대용량 트래픽을 관리해보자 (0) | 2023.10.05 |
Flutter + Spring Security + OAuth2 + JWT, 로그인 후 앱으로 redirect 하는 방법 (0) | 2023.08.23 |