
Controller ➡️ ServiceImpl ➡️ DAO(or Mapper) ➡️ SQLMapper 를 통해 DB에 접근한다.
이 과정 중에 사용되는 데이터 형식은 DTO / VO로 정의된다.
클라이언트의 요청을 받아 해당하는 Service를 호출하여 요청을 처리한다.
@Controller : 이 클래스가 Controller class 임을 명시
@RequestMapping("/~") : 기본 URL 지정
testBoardController.java
@Controller
@RequestMapping("/admin/site2/test-board")
public class TestBoardController {
@Resource(name = "testBoardService")
private TestBoardService testBoardService;
@Autowired
private UserMapper userMapper;
@RequestMapping("")
public String TestBoardList(TestBoardVO seongBoard, ModelMap model) {
model.addAttribute("seongBoard",seongBoard);
List<TestBoardVO> seongBoardList = testBoardService.selectTestBoardList(seongBoard);
model.addAttribute("seongBoardList", seongBoardList);
return "/admin/site2/testBoard_index";
}
요청을 전달 받은 Service는 DB에 접근하는 DAO(or Mapper) 를 이용하여 비즈니스 로직을 수행한다.
interface와 구현 클래스 파일을 구현해야한다.
@Service : 이 클래스가 Service 클래스임을 명시
TestBoardService.java
public interface TestBoardService {
List<TestBoardVO> selectTestBoardList(TestBoardVO testBoardVO) throws Exception;
}
TestBoardServiceImpl.java
@Service("testBoardService")
public class TestBoardServiceImpl extends EgovAbstractServiceImpl implements TestBoardService {
@Resource(name="testBoardMapper")
private TestBoardMapper testBoardMapper;
@Override
public List<TestBoardVO> selectTestBoardList(TestBoardVO testBoardVO) throws Exception {
return testBoardMapper.selectTestBoardList(testBoardVO);
}
}
필요한 DB쿼리를 호출하는 파트
DB의 효율적인 커넥션 관리를 위해 비즈니스 로직과 분리해 둔 것임
Mybatic에서 Mapper 인터페이스를 제공SQL문은 .xml 파일로 저장되어 편리하게 관리할 수 있다.Mybatic : Java에서 RDBMS를 쉽게 사용할 수 있도록 도와주는 프레임워크
@Mapper: 이 클래스가 Mapper 인터페이스임을 명시
TestBoardMapper.java
@Mapper("testBoardMapper")
public interface TestBoardMapper {
List<TestBoardVO> selectTestBoardList(TestBoardVO testBoardVO) throws Exception;
}
testboard.xml
<mapper namespace="testboard.service.impl.TestBoardMapper">
<select id="selectTestBoard" resultType="testboard.service.TestBoardVO">
select * from TS_BOARD where POST_YN = 'Y'
and <![CDATA[
START_DT <= sysdate
and sysdate <= END_DT
and ROWNUM <= 1]]>
</select>
</mapper>
- namespace : Mapper의 전체 경로
- id : Mapper interface의 method 이름과 xml 파일의 id 동일하게 작성
- parameterType: 파라미터 타입
- resultType: 결과값 반환 타입
💡"실제로 DB의 데이터에 접근하는 객체"
Service와 DB를 연결하는 역할을 하며 실제로 DB에 접근하여 data를 삽입, 삭제, 조회, 수정 등 CRUD 기능을 수행
JPA에서 DB에 데이터를 CRUD하는 JpaRepository<>를 상속받는 Repository객체들이 DAO임.
public interface itemRepository extends JpaRepository<Item, Long> {
}
💡"계층 간 데이터 교환을 위한 객체"
인스턴스 개념, 로직을 가지지 않고 getter/setter 메소드만 가진 순수한 데이터 객체 클래스로
DB에서 데이터를 얻어 Service나 Controller 등으로 보낼 때 사용함.
itemEntity
@Data
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "item_name")
private String itemName;
public Item() {} // JPA는 public, protected의 기본 생성자가 필수 !
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
}
}
ItemUpdateDto
@Getter
@Setter
public class ItemUpdateDto {
private String itemName;
public ItemUpdateDto() {
}
public ItemUpdateDto(String itemName) {
this.itemName = itemName;
}
}
itemService.java
@Override
public void update(Long itemId, ItemUpdateDto updateParam) {
Item findItem = itemRepository.findById(itemId).orElseThrow();
findItem.setItemName(updateParam.getItemName());
}
💡"변경 불가능한, Read Only"
리터럴 값 (변하지 않는 데이터), VO는 getter만 가지고 있기 때문에 읽기만 가능하고 수정은 불가능함.
TestBoardVO
<public class TestBoardVO extends Page {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
💡주로 소프트웨어 개발에서 인터페이스의 구현체를 나타내는 용어로 사용됨
ex) UserService라는 인터페이스가 있으면, 해당 인터페이스를 구현하는 클래스 이름은 UserServiceImpl 과 같음.
인터페이스와 구현체 분리
인터페이스는 객체의 추상적인 타입과 메서드 시그니처를 정의하고, Impl은 실제 동작을 구현한다. 이러한 분리는 코드의 유연성과 확장성을 높여준다.
다형성 지원
인터페이스를 통해 다양한 구현체를 교체해가며 사용 가능하다. UserService 인터페이스를 구현하는 UserServiceImplV1, UserServiceImplV2 등을 필요에 따라 변경하여 사용 가능하다.
OCP (개방-폐쇄 원칙) 준수
기존 코드를 변경하지 않고 새로운 기능을 추가할 수 있도록 도와준다. 새로운 구현체를 추가해도 기존 코드에 영향을 주지 않는다.
가독성 향상
인터페이스와 구현체를 분리하여 코드를 더욱 명확하게 이해하고 유지보수하기 쉽게 만든다.
public interface MainService{
String hihi()
}
public class ServiceImplA implements MainService {
@Override
public String hihi() {
return "AAA"
}
}
public class ServiceImplB implements MainService {
@Override
public String hihi() {
return "BBB"
}
}
이렇게 두 개를 사용할 수 있다. 구현체에만 와서 바꿔주면 된다.