티스토리 뷰

이전 포스팅에서 정리했듯

핵심기능의 DB설계가 얼추 마무리 되었으니 이제 스프링으로 넘어가 interface 설계를 진행하겠다.

 

그전에 스프링 프레임 워크를 사용한 웹서비스의 흐름을 따라 인터페이스 설계의 목적을 설명하도록 하겠다.

 

 

왜 인터페이스 설계가 필요한가?

 

 

한가지 예시를 들어 설명하도록 하겠다.

현재 진행하는 식단생성기가 완성되었다 가정하고 웹서비스를 이용하는 유저가

식단생성기 웹에 방문해 정보를 입력 후 식단 생성버튼을 클릭했다라고 가정해보도록 하겠다.

 

 

 

이 과정을 클라이언트의 요청이라 부르는데,

클라이언트의 요청이 발생하게 되면 해당 요청에 대한 정보를 서버로 넘기게 된다.

 

이때 현재 프로젝트에서 사용하기로한 웹서버는 아파치 톰켓 V8.5을 사용하고있고

웹서버를 거쳐 서버컴으로 요청이 전송된다.

 

 

 

 

그리고 이 서버는 요청에 대한 응답을 생성해 다시 클라이언트에게 화면으로 응답하는데

이를 위해 우리는 스프링 프레임워크를 사용해 이 과정을 처리한다.

 

그리고 서버에서의 처리과정을 조금 자세히 설명하자면 다음과 같다.

기본적으로 스프링은 MVC2 패턴을 사용한 흐름으로 요청에 대한 처리가 이루어진다.

따라서 MVC2 패턴의 흐름으로 설명을 진행하고자 한다.

 

먼저 DAO의 인터페이스 설계를 다루는 포스팅이므로 필터와 인터셉터부분에 대한 설명은

다른 포스팅에서 다루도록 하겠다.

 

요청은 필터와 인터셉터를 거쳐서 컨트롤러로 오게되고,

컨트롤러에서는 요청에 따라 비즈니스 로직이 필요한 요청인 경우 서비스로 넘겨 이에 대한

비즈니스 로직으로 처리한다.

 

이때 요청이 식단을 생성해달란 요청이었으므로 그와 관련한 DB에 대한 접근도 필요할것이다.

이 경우 필요한게 바로 DAO와 VO이다.

 

식단을 위한 데이터를 DB에서 받아와야 하므로 DAO를 통해 DB의 자원을 가져와

VO에 매핑하는 작업이 필요하다.

 

 

흐름을 보면 컨트롤러에서는 서비스 객체가 필요하고, 서비스에서는 DAO 객체가 필요하다.

이런 꼬리의 꼬리를 물게되는 흐름이므로 필연적으로 결합도가 높아지게 될것이다.

이를 해결하기 위해 스프링에서는 DI 패턴을 사용하고 필드 주입방식을 통해 결합도를 낮춘다.

 

이 과정에서 DAO를 interface로 설계해 구현받는 객체를 하나만 만들어 필드로 주입받아

DAO를 사용하게되는 서비스단에서 사용할수 있게되는것이다.

 

또 서비스단 역시 interface로 설계해 컨트롤러에서 필드주입을 통해 결합도를 낮출 수 있다.

 

그렇다면 왜 인터페이스인가라는 의문이 들수 있다.

사실 인터페이스가 아니더라도 상속을 통해서도 충분히 결합도를 낮출수 있을텐데

왜 인터페이스인가?

 

먼저 이 부분에 대해서는 필자의 생각이 많이 들어갔음을 알린다.

틀린부분이 있을 수 있고 또 그런 부분에 대해서는 댓글로 얼마든지 지적해도 좋다.

 

조금 근본적으로 들어가 상속과 인터페이스 구현의 차이점에 대해서 생각해보자면,

기능적 측면에서는 상속은 다중상속이 불가하고, 단일 상속만 가능하다.

그러나 인터페이스는 다중 구현이 가능하단 장점이 있다.

 

또 상속은 클래스내부에서 로직이 들어갈수 있다. 물론 추상 메소드로만 작성한다면 로직이

들어가지 않겠지만 과연 그게 의미가 있나 싶다.

반면 인터페이스는 메소드가 추상메소드로만 작성되므로 비유하자면 책에서 목차와 같이

나는 ~~~한 기능을 작성할것이다와 같은 성격을 띈다.

 

따라서 결합도를 낮추기 위한 목적으로 사용하는 DI이니 로직이 들어가지 않고 확장성이 용이한

인터페이스로 설계한다고 필자는 생각한다.

 

덧붙이자면, 스프링 자체적으로 인터페이스의 사용이 권장되며 몇가지 어노테이션들은

인터페이스가 아니라면 사용이 불가능한 어노테이션들도 있다.

 

정리하자면 설계단에서 결합도를 낮추기 위해 작성되는 인터페이스이니

어떤 기능들을 만들것이다란 목차를 작성한다 정도의 개념으로 이해하고 넘어가면 될듯하다.

두번째로 스프링에서 인터페이스의 사용이 권장된다.

 

 


 

 

조금 많이 돌아왔지만, 왜 인터페이스 설계를 하는가에 대한 근거는 이정도면 충분한거 같으니

프로젝트로 돌아와 인터페이스를 작성해보도록하겠다.

 

 

인터페이스 설계

 

 

 

생성된 테이블은 식재료, 식재료상세, 메뉴, 메뉴 상세 테이블이므로

각 테이블에 대한 VO가 필요할것이다.

 

VO에서는 로직이 들어가도 되지만 우선 단순히 매핑을 위한 getter, setter만 작성해

테이블의 컬럼에 대해 대응될수 있도록 만들어 주겠다.

 

예시로 음식테이블에 대한 VO와 interface에 대해서만 소스를 남겨 놓도록 하겠다.

 

먼저 VO 부분이다.

 

package com.human.VO;

public class FoodVO {
	
	private int food_no;
	private String food_name;
	private int food_date;
	private int food_allergy;
	private int food_cost;
	
	public int getFood_no() {
		return food_no;
	}
	
	public void setFood_no(int food_no) {
		this.food_no = food_no;
	}
	
	public String getFood_name() {
		return food_name;
	}
	
	public void setFood_name(String food_name) {
		this.food_name = food_name;
	}
	
	public int getFood_date() {
		return food_date;
	}
	
	public void setFood_date(int food_date) {
		this.food_date = food_date;
	}
	
	public int getFood_allergy() {
		return food_allergy;
	}
	
	public void setFood_allergy(int food_allergy) {
		this.food_allergy = food_allergy;
	}
	
	public int getFood_cost() {
		return food_cost;
	}
	
	public void setFood_cost(int food_cost) {
		this.food_cost = food_cost;
	}
}

 

 

이어서 인터페이스작성을 하겠다.

 

DAO 인터페이스이므로 DB의 CRUD 작업을 위한 기능이 필요할것이므로

insert, select, update 까지만 작성하도록 하겠다. 

식재료 삭제기능은 아직까지는 필요없어 보이므로

굳이 작성하지 않았지만 필요하다면 추후에 추가하면 될것이다.

 

package com.human.dao;

import java.util.List;

import org.springframework.dao.DataAccessException;

import com.human.VO.FoodVO;

public interface IF_FoodDAO {
	
	public void insertFood(FoodVO foodVO) throws DataAccessException, Exception;
	public FoodVO selectOne(int food_no) throws DataAccessException, Exception;
	public List<FoodVO> selectAll() throws DataAccessException, Exception;
	public void updateFoodCost(FoodVO foodVO) throws DataAccessException, Exception;
}

 

 

 

JDBC에서 발생하는 대부분의 예외는 DataAccessException이므로 예외를 던져줄수 있도록 해주었고,

그외에 발생할수 있는 예외에 대해선 Exception으로 예외를 던져주도록 해주었다.

 

이와 같은 과정으로 인터페이스와 VO를 작성한 디렉토리 구조는 다음과 같다.

 

├─dailymeal
│      HomeController.java
│
├─dao
│      IF_FoodDAO.java
│      IF_FoodDetailDAO.java
│      IF_MenuDAO.java
│      IF_MenuDetailDAO.java
│
├─service
└─VO
        FoodDetailVO.java
        FoodVO.java
        MenuDetailVO.java
        MenuVO.java

 

 

 

이어서 Mapper를 만들어 주도록 하겠다.

 

 

 

resources 하위에 mapper 폴더를 만들어 여기서 Mapper를 관리하도록 하겠다.

그리고 DB자원을 관리해줄 프레임워크인 mybatis의 사용을 위해 been등록을 해주도록 하겠다.

 

root-context에서 다음과 같이 작성해준뒤,

 


	<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
		<property name="dataSource" ref="dataSource" />
		<property value="classpath:/mapper/*Mapper.xml" name="mapperLocations" />       
	</bean>

 

	<bean id="sqlSession"
		class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory" />
	</bean>

 

 

이어서 DAO의 경로도 설정해주도록 하겠다.

다음과 같이 스캔할 경로를 작성해준뒤, 

	<context:component-scan
   base-package="com.human.dao"/>

 

 

 

하단의 Namespaces로 이동,

 

 

 

context를 체크해주면 된다.

 

 

그리고 Mapper 파일을 작성하자면

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.human.dao.IF_FoodDAO">

</mapper>

 

 

mapper의 namespace를 해당 매퍼와 매핑할 DAO경로를 작성해주면 된다.

 

 

작성이 완료된 Mapper의 디렉토리 구조는 다음과 같다.

 

│  log4j.xml
│
├─mapper
│      FoodDetailMapper.xml
│      FoodMapper.xml
│      MenuDetailMapper.xml
│      MenuMapperxml.xml
│
└─META-INF

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함