728x90
Service
MVC 패턴은 애플리케이션을 Model, View, Controller 세 가지 주요 구성 요소로 분리하는 디자인 패턴입니다. 지금까지 구현해왔던 FrontController가 DAO를 직접 사용하는 것은 구조 설계 관점에서 높은 결합도를 가지기 때문에 바람직하지 않습니다. 결합도가 높으면 코드의 변경이나 유지보수가 어려워질 수 있습니다. 따라서 Controller와 Service 레이어가 DAO와 상호 작용하고 결합도를 최소화하며 Model로 데이터를 전달해야 합니다.
Interface
인터페이스를 사용하여 DAO와 Service를 정의하는 것은 많은 장점을 가지고 있습니다.
- 추상화, 강제화
- 인터페이스를 사용하여 DAO와 Service를 정의하는 것은 데이터 액세스 계층을 추상화하고 결합도를 낮추는 데 도움이 됩니다. 인터페이스를 통해 메서드를 강제화하면 각 DAO, Service 구현은 일관된 메서드 시그니처를 따라야 하므로 실수를 줄이고 일관성을 유지할 수 있습니다.
- 다형성과 오버라이딩
- 인터페이스를 사용하면 다형성을 활용할 수 있으며, 이는 객체 지향 프로그래밍의 핵심 원칙 중 하나입니다. 다형성을 통해 여러 다른 DAO, Service 구현을 동일한 인터페이스를 사용하여 처리할 수 있습니다.
- 의존성 주입 (Dependency Injection)
- Service 레이어가 인터페이스를 멤버 변수로 가짐으로써 의존성을 주입하는 것은 Spring의 IoC 원칙에 따라서입니다. 이렇게 하면 어떤 클래스가 실제로 주입되는지를 구성을 통해 변경할 수 있으며, 이로써 다른 DAO, Service 구현을 사용하는 것이 가능합니다. 이것은 런타임에 의존성을 결정하므로 코드의 변경 없이 구성만으로 다른 객체를 주입할 수 있습니다.
- 결합도와 유지보수성
- 인터페이스와 의존성 주입을 사용하면 클래스 간의 결합도가 낮아지며, 이는 유지보수성을 향상시킵니다. 클래스 간의 강력한 결합은 코드 변경 시 다른 클래스에 미치는 영향을 크게 미칠 수 있습니다. 따라서 결합도를 낮추는 것은 소프트웨어의 유지 및 개선을 용이하게 만듭니다.
코드 구현
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
728x90