프레임워크
: 어느 정도 완성된 상태로 제공하는 기능
개발 생산성과 품질이 보장된 애플리케이션 개발 가능
스프링 프레임워크
애플리케이션에서 사용되는 여러 빈(클래스 객체)을 스프링이 권한을 가지고 직접 관리
<특징>
- 가벼움
- 제어 역행(IoC) 기술 이용 → 애플리케이션 간 느슨한 결합 제어
- 의존성 주입(DI) 기능 지원
- 관점 지향(AOP) 기능으로 자원 관리
- 영속성과 관련된 다양한 서비스 지원
- 다양한 라이브러리와 연동 기능 지원
제어 역행 : 서블릿이나 빈 등을 프레임워크가 직접 수행
의존성 주입 : 클래스 객체를 프레임워크가 생성 및 사용
관점 지향 : 핵심 기능과 부수 기능 분리 구현 → 모듈성 증가
<기능>
- Core : 다른 기능을 수행하는 데 필요한 기반 기능 및 IoC 기능 제공
- Context : 스프링의 기본 기능, 빈에 대한 접근 방법 제공
- DAO : JDBC 편리하게 사용할 수 있도록
- ORM : 영속성 관련 프레임워크와 연동된 기능 제공
- AOP : 관점 지향 기능 제공
- Web : 웹 애플리케이션 개발에 필요한 기능 제공
- WebMVC : 스프링에서 MVC 구현 관련 기능 제공
의존성 주입
: 사용할 클래스와 사용될 클래스의 관계를 컨테이너가 직접 규정하는 것
의존성 주입 시 직접적인 연관 관계 발생 X → 클래스 변경이 자유로움( 약한 결합 )
강한 결합과 약한 결합
강한 결합 : 변경 사항 발생 시 다른 클래스 수정 필요
약한 결합 : 변경 사항 발생해도 다른 클래스 수정 불필요
서로 관련 있는 기능은 강하게, 관련 없는 기능은 약하게 결합해야 좋은 프로그램!
애플리케이션은 각 기능을 담당하는 컴포넌트로, 컴포넌트는 세부 기능을 수행하는 클래스로 이루어짐.
클래스가 다른 클래스의 기능 사용할 때, 다른 클래스의 생성자를 호출해 사용
→ 구현 과정에서 다른 변경 사항 발생 시 관련 있는 모든 클래스의 소스 코드 수정 필요
→ 빠른 대처 어려움
스프링 프레임워크에서 설정을 통해 맺어줌 → 클래스들이 연관 관계 갖지 않게 구현
의존성 주입 사용 X
//BoardService
public class BoardService {
BoardDAO boardDAO;
public BoardService() {
boardDAO = new BoardDAO(); //BoardDAO 객체를 코드에서 직접 생성
}
...
인터페이스 적용
<계층 구조>
BoardController <-- BoardControllerImpl
BoardService <-- BoardServiceImpl
BoardDAO <-- BoardOracleDAOImpl
//BoardServiceImpl
public class BoardServiceImpl implements BoardService{
BoardDAO boardDAO;
public BoardService(){
boardDAO = new BoardOracleDAOImpl(); //인터페이스를 이용해 하위 클래스 객체 생성 후, 오라클 DB와 연동
}
여기서 MySQL과 연동하는 새로운 기능이 생겼다고 해도 기존의 BoardOracleDAOImpl 클래스
를 변경할 필요 X
BoardDAO 인터페이스를 구현한 또 다른 BoardMySqlDAOImpl 클래스
구현 후 사용하면 됨
//BoardServiceImpl
public class BoardServiceImpl implements BoardService{
BoardDAO boardDAO;
public BoardService(){
boardDAO = new BoardMySqlDAOImpl(); //인터페이스를 이용해 하위 클래스 객체 생성 후, MySQL과 연동
}
인터페이스를 이용해 각 클래스 구현 후 각 클래스 객체 사용할 때는 인터페이스 타입으로 선언한 참조 변수로 접근해 사용
→ 완전하진 않아도 의존 관계가 약해짐 But, BoardServiceImpl
은 여전히 직접 수정 필요
의존성 주입 적용
XML / 애너테이션을 이용해 객체 주입해 객체 간 의존 관계를 맺어줌
<장점>
➖ 클래스들 간 의존 관계 최소화 → 코드 단순화
➖ 쉬운 유지 및 관리
➖ 객체의 생성, 소멸과 객체 간의 의존 관계를 컨테이너가 제어
제어 역전 : 원래는 개발자가 직접 객체를 제어하던 것을 스프링이 직접 담당하는 것
1. 생성자를 이용해 주입하는 방식
//BoardServiceImpl
public class BoardServiceImpl implements BoardService{
private BoardDAO boardDAO;
public BoardServiceImpl(BoardDAO boardDAO){
this.boardDAO = boardDAO;
}
...
BoardService
클래스는 의존하는 BoardDAOImpl
객체를 전달받기 위해 생성자를 호출할 때 외부에서 객체를 주입 받아 사용
BoardSErviceImpl 생성자를 호출할 때 컨테이너에 의해 주입되는 객체로 boardDAO 변수를 초기화한 것
2. setter를 이용하여 주입하는 방식
//BoardServiceImpl
public class BoardServiceImpl implements BoardService{
private BoardDAO boardDAO;
public void setBoardDAO(BoardDAO boardDAO){
this.boardDAO = boardDAO;
}
...
실습
1. setter를 이용한 DI 기능
<계층 구조>
TestService <-- TestServiceImpl
<bean 태그 속성>
속성 이름 | 설명 |
---|---|
id | 빈 객체의 고유 이름, id를 이용해 접근 |
name | 객체의 별칭 |
class | 생성할 클래스, 패키지 이름까지 입력해야 함 |
constructor-arg | 생성자를 이용해 값을 주입할 때 사용 |
property | setter를 이용해 값을 주입할 때 사용 |
new를 이용해 직접 객체를 생성하던 것을 person.xml에서 설정
//person.xml
<bean id="personService" class="com.spring.ex01.PersonServiceImpl">
<property name="name">
//PersonServiceImpl 객체의 속성 name 값을 <value> 태그를 이용해 '홍길동'으로 초기화
<value>홍길동</value>
</property>
</bean>
// PersonServiceImpl
public void setName(String name){
this.name = name; //person.xml에서 지정한 value값을 매개 name에 넣음
}
2. 생성자를 이용한 DI 기능
//person.xml
//인자가 1개인 생성자에 매개값을 value값으로 초기화
<bean id="personService1" class="com.spring.ex02.PersonServiceImpl">
<constructor-arg value="이순신" />
</bean>
//인자가 2개인 생성자에 매개값들을 value값으로 초기화
<bean id="personService2" class="com.spring.ex02.PersonServiceImpl">
<constructor-arg value="손흥민" />
<constructor-arg value="23" />
</bean>
3. 빈에 주입되는 값이 의존 관계에 있는 다른 빈을 주입하는 경우
<계층 구조>
MemberServiceImpl --> MemberService
↓ 의존관계
MemberDAOImpl --> MemberDAO
//member.xml
//빈을 만들면서 setter 주입 방식으로 id가 memberDAO인 빈을 자신의 속성에 주입
<bean id="memberService" class="com.spring.ex03.MemberServiceImpl">
<property name="memberDAO" ref="memberDAO" />
</bean>
<bean id="memberDAO" class="com.spring.ex03.MemberDAOImpl" />
기본형 데이터가 아닌 참조형 데이터는 ref 속성 이용해서 주입해야 함
기본형 데이터 vs 참조형 데이터
기본형: 실제 리터럴 값 저장(boolean, char, byte, short, int, long, float, double)
참조형: 객체의 주소 저장(String, 배열, 클래스, 인터페이스 등 기본형을 제외한 모든 것)