@Configuration 이란?
@Configuration 어노테이션은 스프링 프레임워크에서 사용되는 어노테이션 중 하나로, 해당 클래스를 스프링의 설정 클래스로 지정하는 역할을 합니다.
@Configuration 어노테이션이 적용된 클래스는 스프링의 설정 정보를 포함하고 있는 클래스로 간주됩니다.
@Configuration 어노테이션이 적용된 클래스는 일반적으로 스프링 빈(Bean)의 정의를 포함하고, 스프링 컨테이너에 의해 관리되는 객체들을 생성하는 데 사용됩니다. 이를 통해 스프링은 해당 설정 클래스를 분석하여 빈으로 등록하고 의존성을 주입하며, 컨테이너에서 사용 가능한 객체를 구성합니다.
@ComponentScan 이란?
@ComponentScan 어노테이션은 스프링 프레임워크에서 사용되는 어노테이션 중 하나로, 컴포넌트 스캔(Component Scan)을 설정하는 역할을 합니다.
컴포넌트 스캔은 스프링이 자동으로 빈(Bean)으로 등록할 클래스를 찾아서 컨테이너에 추가하는 기능을 제공합니다.
@ComponentScan 어노테이션은 주로 설정 클래스에 적용되며, 해당 클래스가 속한 패키지와 하위 패키지에서 컴포넌트 스캔을 수행합니다. 스프링은 이 패키지 내의 클래스들을 스캔하여 @Component 어노테이션이 적용된 클래스들을 빈으로 등록합니다.
저번시간에 배운 내용이랑 같은 내용입니다.
대신 사용 방법이 다른 것이지요.
@Repository 란?
@Repository는 스프링 프레임워크에서 사용되는 어노테이션 중 하나로, 데이터 액세스 계층(Data Access Layer)에서 데이터베이스와의 상호작용을 담당하는 클래스에 적용됩니다.
@Repository 어노테이션은 해당 클래스를 스프링의 데이터 액세스 예외 변환 기능과 함께 빈(Bean)으로 등록하는 역할을 합니다.
@Repository 어노테이션은 주로 데이터 액세스 객체(Data Access Object, DAO)를 구현하는 클래스에 적용됩니다. 이 어노테이션은 해당 클래스가 데이터베이스와의 상호작용을 위한 기능을 제공하고, 예외 변환 및 롤백 등의 데이터 액세스 예외 처리를 담당함을 나타냅니다.
Data Access Object 나 Persistence Layer에 명시한다고 합니다.
**Persistence Layer**
Persistence Layer의 주요 목적은 데이터를 영구적으로 저장하고 관리함으로써 데이터의 지속성을 보장하는 것입니다. 이 계층은 데이터베이스와의 상호작용을 담당하며, 데이터베이스와의 통신, 데이터의 CRUD(Create, Read, Update, Delete) 작업, 데이터베이스 트랜잭션 관리 등을 수행합니다.
@Service 란?
@Service는 스프링 프레임워크에서 사용되는 애노테이션 중 하나로, 비즈니스 로직을 처리하는 서비스(Service) 클래스에 적용됩니다. @Service 어노테이션은 해당 클래스를 스프링의 빈(Bean)으로 등록하는 역할을 합니다.
**비즈니스 로직**
비즈니스 로직은 소프트웨어 시스템에서 실제 비즈니스 요구사항을 구현하기 위한 중요한 부분입니다. 이는 조직 또는 기업의 핵심 비즈니스 프로세스나 규칙을 정의하고 구현하는 코드로 이루어져 있습니다.
비즈니스 로직은 비즈니스 요구사항에 따라 데이터 처리, 알고리즘, 규칙 등과 관련된 작업을 수행합니다.
@Autowired 란?
@Autowired는 스프링 프레임워크에서 사용되는 애노테이션 중 하나로, 의존성 자동 주입(Dependency Injection)을 수행하는 데 사용됩니다. @Autowired 어노테이션은 스프링 컨테이너가 해당 타입의 빈을 찾아서 자동으로 주입하는 역할을 합니다.
이제 이론을 봤으니 예시도 봐야겠죠?
위의 어노테이션 예제
<AppConfig.java>
@Configuration
@ComponentScan("myproject")
public class AppConfig {
}
현재 만든 Class를 설정파일로 만들고 myproject 폴더 밑에 있는 Component들을 Scan해와라 라는 명령을 주고 있습니다.
이렇게 작성하면 하위 폴더에 있는 빈(Bean)을 자동으로 등록하여 컨테이너에 추가하는 기능을 제공합니다.
<ProductDAOImpl.java>
@Repository
public class ProductDAOImpl implements ProductDAO {
@Override
public String findProductById(String id) {
return id+"아이디 상품정보 "+getClass().getName();
}
}
ProductDAO의 하위 객체인 Impl 클래스를 만듭니다. SOLID원칙 중 D를 잘 따라야 하기 때문입니다.
이거를 처음에 만들 때 메서드만 작성하고 Eclipse에서 Interface 생성 메뉴를 이용하면 금방 만들더라고요.
오른쪽 마우스 클릭해서 Refactor - Extract Interface 누르고 이름 지정하고 함수도 지정하면 ProductDAOImpl에 대한 Interface를 만들 수 있습니다.
@Repository 어노테이션을 작성한 이유는 DAO 기능이기 때문입니다.
이렇게 Interface로 만드는 이유가 또 있는데요. 만약에 ProductDAOImpl의 2번째 버전이 생성될 수도 있는데, 보통 기존에 있던 메서드는 두고 기능확장을 할 텐데 기존의 틀이 있으면 다음 확장팩을 만들기 쉽기 때문입니다.
게임을 만들 때 아예 새로 없애버리고 만들지 않고 확장팩으로 많이 만들지 않습니까? 그런 느낌입니다.
<ProductDAOImplVer2.java>
@Repository
public class ProductDAOImplVer2 implements ProductDAO {
@Override
public String findProductById(String id) {
return id+"아이디 상품정보 "+getClass().getName();
}
}
<ProductServiceImpl.java>
@Service // business layer 비즈니스 계층에서 사용하는 컴포넌트 계열 어노테이션
public class ProductServiceImpl implements ProductService {
private final ProductDAO productDAO;// 항상 추상 인터페이스 타입으로 관리해야 한다
@Autowired // DI
public ProductServiceImpl(ProductDAO productDAO) {
super();
this.productDAO = productDAO;
}
@Override
public String findProductById(String id) {
return productDAO.findProductById(id);
}
}
Service 계층을 만들어서 DAO 객체를 의존성 주입을 하고 DAO 객체에서 사용하는 함수를 넣습니다.
이렇게 따로 만드는 이유는 나중에도 배우겠지만 비즈니스 로직을 처리하는 것과 DAO 처리를 하는 Class를 따로 만들기 위해서입니다.
Service 계층이기 때문에 @Service를 작성했고, 의존성 주입을 위해 생성자에 DAO를 주입하는 문장이 있어서 @Autowired를 작성했습니다.
이렇게 하고 의존성 역전 원칙을 따르기 위해서 Service도 Interface로 추상화해야 합니다.
<TestDI>
public class TestDI {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);
ProductService service=(ProductService)ctx.getBean("productServiceImpl");
System.out.println(service.findProductById("javaking"));
ctx.close();
}
}
1. 이번에는 AnnotationConfigApplicationContext 객체를 생성하여 AppaConfig.class를 읽어와서 스프링 애플리케이션 콘텍스트를 생성하는 코드입니다.
저번에는 직접 만들어 줬다면 이번에는 어노테이션들을 읽어와서 알아서 컨텍스트를 생성하는 방식이죠.
2. 그다음 productServiceImpl을 불러와서 업케스팅으로 Interface로 연결해 줍니다. SOLID의 리스코프 원칙을 따르는 것 같군요.
3. 그다음 결과를 확인해 보면?
javaking아이디 상품정보 myproject.model.ProductDAOImplVer2
아주 잘 나옵니다.
소감
확실히 설정파일을 사용하면 조금은 더 어려운? 느낌이 드는 경향이 있는데, 이렇게 코드를 작성하면서 어노테이션(주석) 처리를 하면 훨씬 직관적으로 다가갈 수 있다고 생각합니다.
엄청 복잡하지는 않지만 익숙하지 않아 조금은 어렵다고 생각합니다. 코드를 작성할 때도 뭔가 계속 빠뜨리고 나눠지는 것이 많다 보니까 이리저리 파일들을 왔다 갔다 하면서 수정하는 게 조금 어지럽다고도 느끼기도 합니다.
익숙해지기 위해서 더 열심히 공부해야겠습니다.
다음 시간에는 DBCP에 관련해서 공부해 보겠습니다.
'코딩 개발 > Spring' 카테고리의 다른 글
AOP (Aspect Oriented Programming) 관점 지향 프로그래밍 (0) | 2023.07.08 |
---|---|
Spring - DBCP (DataBase Connection Pool) (0) | 2023.07.08 |
applicationContext.xml - @Component Annotation 사용하기 (0) | 2023.07.07 |
xml 파일을 이용한 제어의 역전(IOC)(applicationContext.xml, Maven) (0) | 2023.07.07 |
Spring FrameWork 에 대하여 (+ IOC / DI, 간단한 용어 정리) (0) | 2023.07.07 |