[Spring] Spring DI와 비즈니스 로직

2024. 10. 6. 20:06·Spring

 

오늘은 패키지 구조와 비즈니스 로직에 대해 정리해봤다.

보통 패키지는 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는 몇 가지 어노테이션으로 구체화될 수 있다.

  1. @Repository: DAO 클래스에 사용된다. @Repository는 실제로 사용할 때 @Component와 마찬가지로 작동하며, 따로 ("") 안에 이름을 명시하지 않아도 된다. @Autowired로 자료형을 통해 주입되기 때문에 중복될 걱정이 없다.
  2. @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
'Spring' 카테고리의 다른 글
  • [Spring] DispatcherServlet과 Spring MVC의 핵심 흐름 분석
  • [Spring] DispatcherServlet, ViewResolver , DI 방식 정리
  • [Spring] Spring에서의 객체 관리: XML 설정 파일 vs 어노테이션 기반 DI
  • [Spring] 의존성 주입
yn98
yn98
좌우명 : 여전할 것 인가, 역전할 것 인가? 백엔드 개발자가 되고싶은 역전하고 있는 개발자 꿈나무의 블로그입니다. 개발을 하면서 공부한 것들을 기록합니다. 24.06 ~
  • yn98
    개발 꿈나무
    yn98
  • 전체
    오늘
    어제
    • 분류 전체보기 (131)
      • Python (3)
      • 공부 (7)
      • DB (7)
      • JAVA (24)
      • JSP (9)
      • jQuery (2)
      • HTML (3)
      • Spring (20)
      • 웹 (4)
      • C (1)
      • Git (2)
      • 에러일기 (19)
      • 프로젝트 (6)
      • 책 (21)
        • 멘토씨리즈 자바 (14)
        • 2024 수제비 정보처리기사 (7)
      • 기타 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
    • Notion
  • 공지사항

  • 인기 글

  • 태그

    codeup 4891 : 행복
    객체지향
    html
    생성자
    상속
    이벤트 스케줄러
    ViewResolver
    @repository
    aop
    스프링 프레임워크
    정보처리기사
    jsp
    java
    2-layered 아키텍처
    @service
    Spring
    DispatcherServlet
    정처기 실기
    Di
    오블완
    멘토씨리즈 자바
    MVC
    어노테이션
    recoverabledataaccessexception
    오버로딩
    @Component
    정보처리기사 실기
    수제비
    티스토리챌린지
    정처기
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
yn98
[Spring] Spring DI와 비즈니스 로직
상단으로

티스토리툴바