- Layered Architecture와 MVC 패턴 이해
- @Component 어노테이션 이해와 사용
- Layered Architecture를 이해하고 대표적 활용 사례인 MVC 패턴과 전자정부 프레임워크에 대해 살펴봅니다.
- 어노테이션 기반 개발을 활용한 첫번째 사례를 학습합니다.
- 효율적인 개발과 유지보수를 위해 어플리케이션을 계층화하여 개발하는 것
- 대부분의 중/대규모 어플리케이션에서 적용
- 각 레이어는 독립된 R&R을 가짐
인접한 레이어들끼리만 직접 통신이 가능하고 떨어져 있는 레이어들간의 직접적인 통신은 금지하고 있습니다. Spring의 기본 구조는 아니지만, 일반적으로 Layered Architecture 방식으로 개발하는 것으로 굳어져 있습니다.
사용자는 화면(Presentation Layer)와 소통하고, 데이터베이스는 Data Layer와 소통합니다. 그 중간을 이어주는 것이 Business Layer입니다.
- 사용자와 상호작용을 담당
- 사용자의 요청을 분석/응답
사용자와 직접적으로 맞닿아 있는 영역입니다.
- 핵심 기능을 수행
- 트랜잭션 수행
- 데이터의 저장과 조회를 담당
- 주로 데이터베이스와 연동하여 작업
DAO라고도 합니다.
- Layered Architecture를 사용한 대표적 패턴
- 어플리케이션을 Model, View, Controller로 구분
- UI를 가지는 대부분의 어플리케이션은 MVC 혹은 변형된 MVC 패턴을 사용
- 예) Angular, Android, iOS, SpringNVC 등
Presentation Layer 쪽을 더 세분화 시킨 패턴입니다.
그만큼 Presentation Layer가 중요해지고 높은 수준의 UX가 요구된다는 것입니다.
View는 실질적으로 presentation 영역을 담당합니다.
Model는 화면에 데이터를 바인딩 하기 전에, 데이터를 처리하는 부분입니다.
Controller는 View와 Model의 중간 다리 역할로, 데이터를 제어합니다.
Model 부분이 나중에 Business Layer, Data Layer로 넘어가서 데이터 처리 및 저장을 합니다.
- 어노테이션(Annotation)을 사용
- @Component와 하위 어노테이션을 사용
지난 포스팅까지 우리는 빈 설정 파일에 클래스를 등록해서 사용했었습니다. 하지만 실제 개발을 하다보면 수많은 클래스가 정의될텐데 일일히 선언하기도 지치겠죠? 그럴 때 사용하는 게 어노테이션입니다.
Spring에서는 @Component를 상속한 하위 3개의 어노테이션을 사용합니다.
각 Layer별로 어노테이션을 사용합니다.(그림 참고)
- <context:component-scan base-package="패키지명" />
- 패키지 명 이후 하위 패키지를 검색해 @Component 어노테이션을 포함하는 모든 클래스를 빈으로 자동 등록
어노테이션 사용을 위한 xml 설정파일에 선언 코드입니다.
- Context:component-scan 태그
- Bean이 될 수 있는 모든 Component들을 자동으로 찾아 Bean Container에 등록
- 단, 의존성 관계 등록은 따로 하지 않음
- Autowired
- Component 간의 의존관계는 Autowired 라는 Annotation으로 적용
- Component-scan과 수동(Setter, 생성자) DI는 혼용해서 사용 가능
게시판 글쓰기 기능 구현 실습을 해봅니다. DB 연동은 하지 않았기 때문에 가상으로 insert를 한다고 가정하고 나중에 DB 연동을 해보도록 하겠습니다.
또한 어노테이션을 이용해서 등록해보겠습니다.
구현 전에 생성할 클래스들과 의존성을 짧게 기록하겠습니다.
1. ArticleService class : 게시판 기능 클래스(글 등록, 수정, 삭제 등등 핵심 기능이 있을 것)
2. ArticleDAO class : 게시글 - DB 연동 기능 클래스
3. Article class : 게시글에 대한 클래스
예시로 사용자가 게시판 글을 등록하고자 할 때는, ArticleService.registArticle() -> ArticleDAO.insertArticle() -> 실제 DB에 insert 이렇게...
↑ 새 클래스를 하나 생성합니다.
↑ 클래스 이름은 BbsArticle입니다.
그리고 게시판 글 데이터 객체을 담을 멤버변수를 선언합니다.
이제 게시판 글 데이터(객체)에 대한 DAO 클래스를 만들어보겠습니다.
↑ DAO 클래스를 모아놓은 패키지에 class를 하나 더 생성합니다.
↑ 게시글 클래스를 하나 더 생성합니다.
패키지도 새로 하나 만들었습니다.
↑ 생성자를 만들겠습니다.
↑ defualt 생성자도 만들어주세요.
↑ 각 멤버변수에 접근 할 setter를 생성할 겁니다.
아무데나 우클릭 -> Source -> Generate Getter and Setter 클릭
↑ 마지막으로 toString()도 만듭니다.
↑ 기본적인 메소드들 추가한 상황입니다.
이로써 article에 대한 VO(Value Object) 생성 했습니다.
↑ BbsService 클래스에서 ArticleDAO 클래스를 생성해서 사용하기 때문에 setter injection을 위한 setter를 생성합니다.
↑ 또한 registArticle() 내에 ArticleDAO의 insertArticle()를 호출하는 코드를 작성합니다.
↑ 빈즈 설정 파일에 클래스들을 선언합니다.
BbsService 객체와 ArticleDAO 객체간의 의존관계도 선언합니다.
Article 객체(VO)는 선언하지 않습니다. 왜냐하면 이 실습에서 컨테이너에 의해 관리되지 않고 저희가 main()에서 직접 new 연산자를 사용해서 생성할 겁니다.
간단한 게시판 구현이라서...
↑ main() 코드입니다.
↑ 실행 결과입니다.
이제 Beans 설정 파일에 선언하지 않고 자동 등록해보겠습니다.
↑ BbsService 클래스 위에 @Service를 작성합니다.
이렇게 간단하게 한 줄 작성함으로써 BbsService 클래스를 컴포넌트로써 사용할 수 있습니다.
↑ ArticleDAO 클래스 위에 @Reposity를 작성합니다.
이제 설정파일로 가서 <context: component-scan ...>를 작성하면 됩니다.
↑ 설정 파일 -> Namespaces 클릭 -> context 체크박스 클릭
↑ 설정 파일의 Source 부분으로 돌아오면 context를 사용할 수 있도록 코드 한 줄이 추가된 것을 볼 수 있습니다.
↑ 한 줄 작성합니다.
base-package 값으로 hello패키지명을 넣었는데요, 이 뜻은 hello 패키지를 포함한 하위 모든 패키지에서 컴포넌트 어노테이션이 붙어있는 클래스들을 전부 다 스캔해서 자동 로딩 해주겠다는 뜻입니다.
↑ 실행 결과, 에러가 납니다.
원인은 DI가 안되서입니다. 어노테이션을 활용한 Bean 자동 등록은 의존 관계 정의까지는 해주지 않습니다.
그래서 구체적으로는 articleService.registArticle()에서 articleDAO 객체에 접근하면서 에러가 난 것입니다.
해결을 위해 @Autowired를 사용합니다.
↑ 이렇게 작성함으로써 자동으로 DI 기능을 해줍니다.
↑ 실행 결과입니다. 정상적으로 작동합니다.
이렇게 자동으로 Bean을 컨테이너에 등록하는 3가지 컴포넌트 어노테이션과 자동 DI 기능인 @Autowired 어노테이션에 대해 학습했습니다.