🍀 Spring Boot

[Spring Boot] Day93 - Service / Interface

harveydent 2023. 9. 21. 13:29
728x90

Service

MVC 패턴은 애플리케이션을 Model, View, Controller 세 가지 주요 구성 요소로 분리하는 디자인 패턴입니다. 지금까지 구현해왔던 FrontController가 DAO를 직접 사용하는 것은 구조 설계 관점에서 높은 결합도를 가지기 때문에 바람직하지 않습니다. 결합도가 높으면 코드의 변경이나 유지보수가 어려워질 수 있습니다. 따라서 Controller와 Service 레이어가 DAO와 상호 작용하고 결합도를 최소화하며 Model로 데이터를 전달해야 합니다.

 

Interface

인터페이스를 사용하여 DAO와 Service를 정의하는 것은 많은 장점을 가지고 있습니다.

  1. 추상화, 강제화
    • 인터페이스를 사용하여 DAO와 Service를 정의하는 것은 데이터 액세스 계층을 추상화하고 결합도를 낮추는 데 도움이 됩니다. 인터페이스를 통해 메서드를 강제화하면 각 DAO, Service 구현은 일관된 메서드 시그니처를 따라야 하므로 실수를 줄이고 일관성을 유지할 수 있습니다.
  2. 다형성과 오버라이딩
    • 인터페이스를 사용하면 다형성을 활용할 수 있으며, 이는 객체 지향 프로그래밍의 핵심 원칙 중 하나입니다. 다형성을 통해 여러 다른 DAO, Service 구현을 동일한 인터페이스를 사용하여 처리할 수 있습니다.
  3. 의존성 주입 (Dependency Injection)
    • Service 레이어가 인터페이스를 멤버 변수로 가짐으로써 의존성을 주입하는 것은 Spring의 IoC 원칙에 따라서입니다. 이렇게 하면 어떤 클래스가 실제로 주입되는지를 구성을 통해 변경할 수 있으며, 이로써 다른 DAO, Service 구현을 사용하는 것이 가능합니다. 이것은 런타임에 의존성을 결정하므로 코드의 변경 없이 구성만으로 다른 객체를 주입할 수 있습니다.
  4. 결합도와 유지보수성
    • 인터페이스와 의존성 주입을 사용하면 클래스 간의 결합도가 낮아지며, 이는 유지보수성을 향상시킵니다. 클래스 간의 강력한 결합은 코드 변경 시 다른 클래스에 미치는 영향을 크게 미칠 수 있습니다. 따라서 결합도를 낮추는 것은 소프트웨어의 유지 및 개선을 용이하게 만듭니다.

 

코드 구현

package com.jun.app;

import java.util.List;

public interface InterfaceBoardDAO {
	public List<BoardDTO> selectAll(BoardDTO bDTO);
	public BoardDTO selectOne(BoardDTO bDTO);
	public boolean insert(BoardDTO bDTO);
	public boolean update(BoardDTO bDTO);
	public boolean delete(BoardDTO bDTO);
}

InterfaceBoardDAO.java

 

package com.jun.app;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class BoardDAO implements InterfaceBoardDAO{

	@Autowired
	private JdbcTemplate jdbcTemplate;

	private final String SELECTALL="SELECT * FROM BOARD ORDER BY BID DESC";
	private final String SELECTONE="SELECT * FROM BOARD WHERE BID=?";
	private final String INSERT="INSERT INTO BOARD VALUES((SELECT NVL(MAX(BID),100)+1 FROM BOARD),?,?)";
	private final String UPDATE="UPDATE BOARD SET CONTENT=? WHERE BID=?";
	private final String DELETE="DELETE FROM BOARD WHERE BID=?";

	@Override
	public List<BoardDTO> selectAll(BoardDTO bDTO) {
		return jdbcTemplate.query(SELECTALL, new BeanPropertyRowMapper<BoardDTO>(BoardDTO.class));
	}
	@Override
	public BoardDTO selectOne(BoardDTO bDTO) {
		Object[] args= { bDTO.getBid() };
		try {
			return jdbcTemplate.queryForObject(SELECTONE, args, new BeanPropertyRowMapper<BoardDTO>(BoardDTO.class));
		}
		catch(Exception e) {
			return null;
		}
	}
	@Override
	public boolean insert(BoardDTO bDTO) {
		int result=jdbcTemplate.update(INSERT, bDTO.getMid(), bDTO.getContent());
		return result>0 ? true : false;
	}
	@Override
	public boolean update(BoardDTO bDTO) {
		int result=jdbcTemplate.update(UPDATE, bDTO.getContent(), bDTO.getBid());
		return result>0 ? true : false;
	}
	@Override
	public boolean delete(BoardDTO bDTO) {
		int result=jdbcTemplate.update(DELETE, bDTO.getBid());
		return result>0 ? true : false;
	}
}

BoardDAO.java

 

package com.jun.app;

import java.util.List;

public interface InterfaceBoardService {
	List<BoardDTO> selectAll(BoardDTO bDTO);
	BoardDTO selectOne(BoardDTO bDTO);
	boolean insert(BoardDTO bDTO);
	boolean update(BoardDTO bDTO);
	boolean delete(BoardDTO bDTO);
}

InterfaceBoardService.java

 

package com.jun.app;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BoardService implements InterfaceBoardService {

	@Autowired
	private InterfaceBoardDAO bDAO;
	
	@Override
	public List<BoardDTO> selectAll(BoardDTO bDTO) {
		return bDAO.selectAll(bDTO);
	}

	@Override
	public BoardDTO selectOne(BoardDTO bDTO) {
		return bDAO.selectOne(bDTO);
	}

	@Override
	public boolean insert(BoardDTO bDTO) {
		return bDAO.insert(bDTO);
	}

	@Override
	public boolean update(BoardDTO bDTO) {
		return bDAO.update(bDTO);
	}

	@Override
	public boolean delete(BoardDTO bDTO) {
		return bDAO.delete(bDTO);
	}
}

BoardService.java

 

package com.jun.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import jakarta.servlet.http.HttpSession;

@Controller
public class CTRL {

	@Autowired
	private InterfaceBoardService boardService;
	@Autowired
	private InterfaceMemberService memberService;

	@GetMapping("/")
	public String root(Model model) {
		model.addAttribute("datas", boardService.selectAll(null));
		return "main";
	}

	@PostMapping("/join")
	public String join(MemberDTO mDTO) {
		memberService.insert(mDTO);
		return "redirect:/";
	}
	@RequestMapping("/login")
	public String login(MemberDTO mDTO, HttpSession session) {
		try {
			mDTO=memberService.selectOne(mDTO); // throws 대신, error.jsp를 views 하위에 위치시켜도 ㄱㅊ
		} catch (Exception e) {
			mDTO=null;
		}
		if(mDTO!=null) {
			session.setAttribute("member", mDTO.getMid());
		}
		return "redirect:/";
	}
	@GetMapping("/logout")
	public String logout(HttpSession session) {
		session.removeAttribute("member");
		return "redirect:/";
	}
	@GetMapping("/mypage")
	public String mypage() {
		return "mypage";
	}
	@PostMapping("/mypage")
	public String mypage(MemberDTO mDTO) {
		memberService.update(mDTO);	
		return "redirect:logout";
	}
	@GetMapping("/deleteAccount/{mid}")
	public String deleteAccount(MemberDTO mDTO) {
		memberService.delete(mDTO);
		return "redirect:/logout";
	}

	@GetMapping("/insert")
	public String insert() {
		return "insert";
	}
	@PostMapping("/insert")
	public String insert(BoardDTO bDTO) {
		boardService.insert(bDTO);
		return "redirect:/";
	}
	@GetMapping("/board/{bid}")
	public String board(BoardDTO bDTO, Model model) {
		try {
			model.addAttribute("board", boardService.selectOne(bDTO)); // .selectOnt()이 예외처리를 미뤄버려서 에러발생!
		}
		catch (Exception e) {
			return "error";
			// forward  V  VR가 동작(/WEB-INF/views/ + 경로 + .jsp)
			// redirect  C
		}
		return "board";
	}
	@PostMapping("/update")
	public String update(BoardDTO bDTO) {
		System.out.println("bDTO : "+bDTO);
		boardService.update(bDTO);
		return "redirect:/board/"+bDTO.getBid();
	}
	@GetMapping("/delete/{bid}")
	public String delete(BoardDTO bDTO) {
		boardService.delete(bDTO);
		return "redirect:/";
	}
}

CTRL.java

Controller에서 InterfaceBoardService와 InterfaceMemberService에 @Autowired 어노테이션을 사용하여 인터페이스 구현체에 대한 의존성을 주입합니다. 이는 코드의 결합도를 낮추고 유지보수를 용이하게 만드는 데 도움이 됩니다.

GitHub

https://github.com/Qkrwnsgus0522/SpringBoot

 

GitHub - Qkrwnsgus0522/SpringBoot

Contribute to Qkrwnsgus0522/SpringBoot development by creating an account on GitHub.

github.com

 

 

728x90