오늘은 패키지 구조와 비즈니스 로직에 대해 정리해봤다.
보통 패키지는 3계층으로 나누는데, 회사명, 어플리케이션명(팀이나 프로젝트), 그리고 제공하는 서비스명으로 구성한다.
아래 사진이 그 예시이다.
핵심은 비즈니스 로직, 즉 비즈니스 메서드인데, 이것은 CRUD 작업이나 핵심 로직을 담당한다.
이 로직을 수행하는 방식은 서비스 계층을 통해 DAO를 호출하는 것과 같다.
예를 들어, XXX.do 요청이 들어오면, FC에서 XxxAction 객체를 생성하고, Action 객체는 execute() 메서드를 호출해 다음 페이지로 이동할 수 있는 AF를 반환한다.
이 과정에서 실질적으로 서비스 내용은 DAO가 수행하는데, 서비스는 이를 핸들링하는 역할이다.
서비스는 마치 폰이라면, DAO는 그 폰의 기능을 실제로 수행하는 시계 같은 느낌이다.
여기서 FC는 Front Controller의 약자로, 웹 애플리케이션에서 클라이언트의 요청을 받아 해당 요청을 처리할 적절한 컨트롤러로 분배하는 역할을 한다. 보통 Spring의 DispatcherServlet이 Front Controller로 작동하며, 모든 요청을 한 곳에서 처리하고, 이후 적절한 서비스나 비즈니스 로직으로 연결하는 데 쓰인다.
AF는 Action Forward의 약자로, 웹 애플리케이션에서 특정 작업(Action)이 완료된 후 어느 페이지로 이동할지 결정하는 정보를 담은 객체를 의미한다. 예를 들어, 특정 비즈니스 로직이 처리된 후, 결과를 보여주기 위해 어느 Front 페이지로 이동할지 설정하는 과정에서 사용된다.
인터페이스와 구현체 관계도 중요하다.
package com.koreait.app.biz.member;
import java.util.List;
public interface MemberService {
List<MemberDTO> selectAll(MemberDTO memberDTO);
MemberDTO selectOne(MemberDTO memberDTO);
boolean insert(MemberDTO memberDTO);
boolean update(MemberDTO memberDTO);
boolean delete(MemberDTO memberDTO);
}
위의 MemberService 인터페이스는 DAO 메서드 시그니처와 동일해야 한다.
구현체(Impl)가 필요한데, 그 역할을 Implement 클래스가 담당한다.
위처럼 강제 오버라이딩을 시키면, 아래와 같은 코드를 쉽게 짤 수 있다.
package com.koreait.app.biz.member;
import java.util.List;
// 인터페이스인 MemberService의 구현체(실현체)
public class MemberServiceImpl implements MemberService {
@Override
public MemberDTO selectOne(MemberDTO memberDTO) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean insert(MemberDTO memberDTO) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean update(MemberDTO memberDTO) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean delete(MemberDTO memberDTO) {
// TODO Auto-generated method stub
return false;
}
@Override
public List<MemberDTO> selectAll(MemberDTO memberDTO) {
// TODO Auto-generated method stub
return null;
}
}
위 코드의 일부를 작성해보자.
@Override
public List<MemberDTO> selectAll(MemberDTO memberDTO) {
MemberDAO memberDAO = new MemberDAO();
List<MemberDTO> datas = memberDAO.selectAll(memberDTO);
return datas;
}
List 부분만 작성해봤는데, 예전보다 훨씬 코드가 간결해진 것을 알 수 있다.
하지만, 이 코드 또한 좋은 코드는 아니다. new 키워드가 들어가있기 때문이다.
selectAll할 때마다 new가 되는 것은 메모리를 낭비시킨다.
이를 해결하기 위해 Spring에서는 DI를 사용해 new 키워드를 없앨 수 있다.
Spring의 @Component 어노테이션을 통해 MemberDAO를 Spring 컨테이너에 등록하고, 자동으로 주입시킬 수 있다.
@Component는 클래스에 붙여서 이 클래스를 Spring이 관리하는 Bean으로 등록하는 역할을 한다. 이때 @Component는 몇 가지 어노테이션으로 구체화될 수 있다.
- @Repository: DAO 클래스에 사용된다. @Repository는 실제로 사용할 때 @Component와 마찬가지로 작동하며, 따로 ("") 안에 이름을 명시하지 않아도 된다. @Autowired로 자료형을 통해 주입되기 때문에 중복될 걱정이 없다.
- @Service: 주로 비즈니스 로직을 처리하는 ServiceImpl 클래스나 Action 클래스 등에 사용된다. 사용자가 호출할 수 있도록 Bean 이름을 지정할 수 있으며, 이로써 서비스를 찾아서 사용할 수 있게 된다.
아래는 위 어노테이션 사용의 예시 코드이다.
// 사용자가 지정
@Service("memberService")
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberDAO memberDAO;
@Override
public List<MemberDTO> selectAll(MemberDTO memberDTO) {
return this.memberDAO.selectAll(memberDTO);
}
// 나머지 CRUD 메서드도 동일한 방식으로 구현
}
// 따로 ("") 할 필요 없음
@Repository
public class MemberDAO {
public List<MemberDTO> selectAll(MemberDTO memberDTO) {
List<MemberDTO> memberList = new ArrayList<>();
Connection conn = JDBCUtil.connect(); // DB 연결
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement("SELECT * FROM MEMBER");
rs = pstmt.executeQuery();
while (rs.next()) {
MemberDTO member = new MemberDTO();
member.setMid(rs.getString("mid"));
member.setPassword(rs.getString("password"));
member.setName(rs.getString("name"));
member.setRole(rs.getString("role"));
memberList.add(member);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.disconnect(pstmt, conn);
}
return memberList;
}
}
Spring을 사용하면 new 키워드를 사용하지 않고도 객체를 주입받아 사용할 수 있는 편리한 환경이 제공된다.
이로 인해 코드가 간결해지고, 객체 관리가 쉬워진다.
또한 DAO와 Service 계층의 분리로, 코드의 유지보수성과 확장성이 높아진다.
'Spring' 카테고리의 다른 글
[Spring] DispatcherServlet과 Spring MVC의 핵심 흐름 분석 (0) | 2024.10.07 |
---|---|
[Spring] DispatcherServlet, ViewResolver , DI 방식 정리 (0) | 2024.10.07 |
[Spring] Spring에서의 객체 관리: XML 설정 파일 vs 어노테이션 기반 DI (4) | 2024.10.04 |
[Spring] 의존성 주입 (0) | 2024.10.02 |
[Spring] 스프링 프레임워크 (1) | 2024.10.01 |