전자정부 프레임워크 공부

전자정부 프레임워크 3.10 - sampleService.selectSampleList

그랜파 개발자 2025. 5. 19. 10:59

아래 두 줄의 코드는 Spring MVC에서 서비스 계층을 통해 데이터를 조회하고, 그 데이터를 뷰(JSP 등)에 전달하기 위해 모델에 담는 전형적인 패턴입니다.

    List<?> sampleList = sampleService.selectSampleList(searchVO);
    model.addAttribute("resultList", sampleList);

🔍 각 줄 설명

1. List<?> sampleList = sampleService.selectSampleList(searchVO);

  • sampleService는 비즈니스 로직을 처리하는 Service 계층의 객체입니다.
  • selectSampleList(searchVO) 메서드는 searchVO (검색/페이징 정보를 담은 객체)를 기반으로 DB에서 데이터를 조회합니다.
  • 반환값은 조회된 데이터 리스트이며, List<?>는 어떤 타입의 객체 리스트인지 명시하지 않은 제네릭 타입입니다.
    • 보통은 List처럼 특정 VO(Value Object) 타입이 사용됩니다.

2. model.addAttribute("resultList", sampleList);

  • model은 Spring MVC에서 뷰로 데이터를 전달할 때 사용하는 객체입니다 (org.springframework.ui.ModelMap).
  • "resultList"라는 이름으로 sampleList 데이터를 뷰에 전달합니다.
    • 예: JSP에서는 ${resultList}로 접근 가능.

📋 결과적으로

이 두 줄은 다음과 같은 의미입니다:

"Service 계층을 통해 조회한 샘플 목록을 resultList라는 이름으로 모델에 담아, 뷰에서 사용할 수 있도록 한다."


📌 JSP에서의 사용 예 (뷰)

<c:forEach var="item" items="${resultList}">
    <tr>
        <td>${item.name}</td>
        <td>${item.description}</td>
    </tr>
</c:forEach>

 

EgovSampleService.java

package egovframework.example.sample.service;

import java.util.List;

/**
 * @Class Name : EgovSampleService.java
 * @Description : EgovSampleService Class
 * @Modification Information
 * @
 * @  수정일      수정자              수정내용
 * @ ---------   ---------   -------------------------------
 * @ 2009.03.16           최초생성
 *
 * @author 개발프레임웍크 실행환경 개발팀
 * @since 2009. 03.16
 * @version 1.0
 * @see
 *
 *  Copyright (C) by MOPAS All right reserved.
 */
public interface EgovSampleService {

    /**
     * 글을 등록한다.
     * @param vo - 등록할 정보가 담긴 SampleVO
     * @return 등록 결과
     * @exception Exception
     */
    String insertSample(SampleVO vo) throws Exception;

    /**
     * 글을 수정한다.
     * @param vo - 수정할 정보가 담긴 SampleVO
     * @return void형
     * @exception Exception
     */
    void updateSample(SampleVO vo) throws Exception;

    /**
     * 글을 삭제한다.
     * @param vo - 삭제할 정보가 담긴 SampleVO
     * @return void형
     * @exception Exception
     */
    void deleteSample(SampleVO vo) throws Exception;

    /**
     * 글을 조회한다.
     * @param vo - 조회할 정보가 담긴 SampleVO
     * @return 조회한 글
     * @exception Exception
     */
    SampleVO selectSample(SampleVO vo) throws Exception;

    /**
     * 글 목록을 조회한다.
     * @param searchVO - 조회할 정보가 담긴 VO
     * @return 글 목록
     * @exception Exception
     */
    List<?> selectSampleList(SampleDefaultVO searchVO) throws Exception;

    /**
     * 글 총 갯수를 조회한다.
     * @param searchVO - 조회할 정보가 담긴 VO
     * @return 글 총 갯수
     * @exception
     */
    int selectSampleListTotCnt(SampleDefaultVO searchVO);

}

 

EgovSampleServiceImpl.java

package egovframework.example.sample.service.impl;

import java.util.List;

import egovframework.example.sample.service.EgovSampleService;
import egovframework.example.sample.service.SampleDefaultVO;
import egovframework.example.sample.service.SampleVO;

import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @Class Name : EgovSampleServiceImpl.java
 * @Description : Sample Business Implement Class
 * @Modification Information
 * @
 * @  수정일      수정자              수정내용
 * @ ---------   ---------   -------------------------------
 * @ 2009.03.16           최초생성
 *
 * @author 개발프레임웍크 실행환경 개발팀
 * @since 2009. 03.16
 * @version 1.0
 * @see
 *
 *  Copyright (C) by MOPAS All right reserved.
 */

@Service("sampleService")
public class EgovSampleServiceImpl extends EgovAbstractServiceImpl implements EgovSampleService {

    private static final Logger LOGGER = LoggerFactory.getLogger(EgovSampleServiceImpl.class);

    /** SampleDAO */
    // TODO ibatis 사용
    @Resource(name = "sampleDAO")
    private SampleDAO sampleDAO;
    // TODO mybatis 사용
    //  @Resource(name="sampleMapper")
    //    private SampleMapper sampleDAO;

    /** ID Generation */
    @Resource(name = "egovIdGnrService")
    private EgovIdGnrService egovIdGnrService;

    /**
     * 글을 등록한다.
     * @param vo - 등록할 정보가 담긴 SampleVO
     * @return 등록 결과
     * @exception Exception
     */
    @Override
    public String insertSample(SampleVO vo) throws Exception {
        LOGGER.debug(vo.toString());

        /** ID Generation Service */
        String id = egovIdGnrService.getNextStringId();
        vo.setId(id);
        LOGGER.debug(vo.toString());

        sampleDAO.insertSample(vo);
        return id;
    }

    /**
     * 글을 수정한다.
     * @param vo - 수정할 정보가 담긴 SampleVO
     * @return void형
     * @exception Exception
     */
    @Override
    public void updateSample(SampleVO vo) throws Exception {
        sampleDAO.updateSample(vo);
    }

    /**
     * 글을 삭제한다.
     * @param vo - 삭제할 정보가 담긴 SampleVO
     * @return void형
     * @exception Exception
     */
    @Override
    public void deleteSample(SampleVO vo) throws Exception {
        sampleDAO.deleteSample(vo);
    }

    /**
     * 글을 조회한다.
     * @param vo - 조회할 정보가 담긴 SampleVO
     * @return 조회한 글
     * @exception Exception
     */
    @Override
    public SampleVO selectSample(SampleVO vo) throws Exception {
        SampleVO resultVO = sampleDAO.selectSample(vo);
        if (resultVO == null)
            throw processException("info.nodata.msg");
        return resultVO;
    }

    /**
     * 글 목록을 조회한다.
     * @param searchVO - 조회할 정보가 담긴 VO
     * @return 글 목록
     * @exception Exception
     */
    @Override
    public List<?> selectSampleList(SampleDefaultVO searchVO) throws Exception {
        return sampleDAO.selectSampleList(searchVO);
    }

    /**
     * 글 총 갯수를 조회한다.
     * @param searchVO - 조회할 정보가 담긴 VO
     * @return 글 총 갯수
     * @exception
     */
    @Override
    public int selectSampleListTotCnt(SampleDefaultVO searchVO) {
        return sampleDAO.selectSampleListTotCnt(searchVO);
    }

}

 

 

아래 코드는 Service 계층의 메서드 구현부로, 실제 데이터베이스 조회 작업을 DAO에 위임하는 간단한 구조입니다:

@Override
public List<?> selectSampleList(SampleDefaultVO searchVO) throws Exception {
    return sampleDAO.selectSampleList(searchVO);
}

🔍 상세 설명

요소 설명
@Override 이 메서드는 인터페이스 (SampleService)에서 정의한 selectSampleList 메서드를 구현하고 있음을 나타냅니다.
List<?> 여러 개의 결과를 리스트 형태로 반환합니다. 실제로는 List와 같은 구체 타입으로 사용되기도 합니다.
selectSampleList(SampleDefaultVO searchVO) searchVO는 검색 조건(페이지 번호, 페이지 크기, 키워드 등)을 담은 객체입니다.
sampleDAO.selectSampleList(searchVO) DAO 계층의 메서드를 호출하여, 데이터베이스에서 결과를 조회합니다.
throws Exception 예외 발생 시 호출한 쪽에서 처리할 수 있도록 예외를 던집니다.

🔁 흐름 요약 (3계층 구조)

Controller
   ↓
Service (selectSampleList)
   ↓
DAO (selectSampleList)
   ↓
DB (SQL 실행 후 결과 반환)

즉,

  • Controller: 클라이언트 요청을 받아 Service 호출
  • Service: 비즈니스 로직 담당 (여기선 로직 없이 DAO만 호출)
  • DAO: DB 접근, SQL 실행

📝 예시로 표현하면

// Controller
List<?> list = sampleService.selectSampleList(searchVO);

// Service
→ DAO에게 위임
return sampleDAO.selectSampleList(searchVO);

// DAO
→ MyBatis, JdbcTemplate 등으로 SQL 실행
SELECT * FROM sample_table WHERE ...

다음 코드는 **DAO 계층에서 단일 레코드(데이터 한 건)**를 조회하는 메서드입니다:

public SampleVO selectSample(SampleVO vo) throws Exception {
    return (SampleVO) select("sampleDAO.selectSample", vo);
}

🔍 상세 설명

구성 요소 설명
public SampleVO selectSample(SampleVO vo) SampleVO 객체를 파라미터로 받아, 해당 조건에 맞는 데이터 1건을 조회하여 SampleVO로 반환하는 메서드입니다.
throws Exception SQL 실행이나 데이터 조회 중 예외 발생 가능성을 호출한 쪽에 위임합니다.
select(...) 이는 일반적으로 EgovAbstractMapperEgovAbstractDAO에서 제공하는 메서드로, SQL을 실행하고 결과 객체를 반환합니다.
"sampleDAO.selectSample" 이 문자열은 SQL 매핑 ID입니다. 보통 MyBatis의 Mapper XML에 정의된 SQL의 ID를 의미합니다.
vo SQL 실행 시 조건으로 사용될 파라미터입니다. (WHERE id = #{id} 같은 SQL에 매핑됨)

🔁 전체 흐름 예시

// Controller
SampleVO result = sampleService.selectSample(vo);

// Service
return sampleDAO.selectSample(vo);

// DAO
return (SampleVO) select("sampleDAO.selectSample", vo);

// Mapper XML (예시 - MyBatis)
<select id="selectSample" resultType="SampleVO" parameterType="SampleVO">
    SELECT * FROM sample_table WHERE id = #{id}
</select>

🧠 추가 설명

  • select(...)는 내부적으로 SqlSession.selectOne(...) 같은 방식으로 동작합니다.
  • "sampleDAO.selectSample"은 보통 sample-mapper.xml 같은 MyBatis 매퍼 XML 파일에서 정의되어야 합니다.
<!-- sample-mapper.xml -->
<mapper namespace="sampleDAO">
  <select id="selectSample" resultType="egovframework.example.sample.service.SampleVO" parameterType="egovframework.example.sample.service.SampleVO">
    SELECT * FROM sample_table WHERE id = #{id}
  </select>
</mapper>

 

 

MyBatis 매퍼 XML 파일은 어디에?

 

ChatGPT의 말:

MyBatis 매퍼 XML 파일은 보통 다음 경로 중 하나에 위치합니다:


1. 일반적인 위치 (표준 Egov 프로젝트 구조 기준)

src/main/resources/egovframework/mapper/sample/sample-mapper.xml

예를 들어:

프로젝트 루트
 └── src
     └── main
         └── resources
             └── egovframework
                 └── mapper
                     └── sample
                         └── sample-mapper.xml

2. 매퍼 XML의 매핑 위치 설정 확인 방법

매퍼 XML 파일이 실제로 어디에 있는지는 Spring 설정 파일 또는 MyBatis 설정 파일에서 확인할 수 있습니다.

예시: context-mapper.xml 또는 context-datasource.xml 내 설정

<!-- Mapper 위치 설정 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations" value="classpath*:egovframework/mapper/**/*.xml" />
</bean>

위 설정에서 mapperLocations 경로를 보면:

  • classpath*:egovframework/mapper/**/*.xml
    → resources/egovframework/mapper/ 하위 모든 .xml 파일을 매퍼로 인식합니다.

3. Mapper 인터페이스와 XML 매핑

예를 들어 DAO 또는 Mapper 인터페이스에서 아래와 같이 매핑할 경우:

// sampleDAO.java or SampleMapper.java
List<SampleVO> selectSampleList(SampleDefaultVO searchVO);

XML 매퍼 파일 (sample-mapper.xml)에는 다음과 같이 정의되어야 합니다:

<!-- sample-mapper.xml -->
<mapper namespace="sampleDAO">
    <select id="selectSampleList" resultType="SampleVO" parameterType="SampleDefaultVO">
        SELECT * FROM sample_table
        WHERE title LIKE CONCAT('%', #{searchKeyword}, '%')
    </select>
</mapper>

🔎 요약

항목 내용
일반 위치 src/main/resources/egovframework/mapper/sample/sample-mapper.xml
위치 지정 Spring 설정 파일의 mapperLocations 프로퍼티로 지정
네임스페이스 → Java 인터페이스나 DAO에서 지정한 이름과 일치해야 함

 

전자정부 프레임워크 3.10 - EgovSample_Sample_SQL.xml

<?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="egovframework.example.sample.service.impl.SampleMapper">

	<resultMap id="sample" type="egovframework.example.sample.service.SampleVO">
		<result property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="description" column="description"/>
		<result property="useYn" column="use_yn"/>
		<result property="regUser" column="reg_user"/>
	</resultMap>

	<insert id="insertSample" parameterType="SampleVO">

			INSERT INTO SAMPLE
				( ID
				  , NAME
				  , DESCRIPTION
				  , USE_YN
				  , REG_USER )
			VALUES ( #{id}
				  , #{name}
				  , #{description}
				  , #{useYn}
				  , #{regUser} )

	</insert>

	<update id="updateSample">

			UPDATE SAMPLE
			SET ID=#{id}
				, NAME=#{name}
				, DESCRIPTION=#{description}
				, USE_YN=#{useYn}
				  WHERE ID=#{id}

	</update>

	<delete id="deleteSample">

			DELETE FROM SAMPLE
			WHERE ID=#{id}

	</delete>

	<select id="selectSample" resultMap="sample">

			SELECT
				ID, NAME, DESCRIPTION, USE_YN, REG_USER
			FROM SAMPLE
			WHERE ID=#{id}

	</select>

	<select id="selectSampleList" parameterType="searchVO" resultType="egovMap">

			SELECT
				ID, NAME, DESCRIPTION, USE_YN, REG_USER
			FROM SAMPLE
			WHERE 1=1
			<if test="searchKeyword != null and searchKeyword != ''">
		        <choose>
		            <when test="searchCondition == 0">
						AND	ID LIKE '%' || #{searchKeyword} || '%'
					</when>
		            <when test="searchCondition == 1">
						AND	NAME LIKE '%' || #{searchKeyword} || '%'
					</when>
				</choose>
			</if>
			ORDER BY ID ASC
			LIMIT #{recordCountPerPage} OFFSET #{firstIndex}
	</select>

	<select id="selectSampleListTotCnt" parameterType="searchVO" resultType="int">

			SELECT COUNT(*) totcnt
			FROM SAMPLE
			WHERE 1=1
			<if test="searchKeyword != null and searchKeyword != ''">
		        <choose>
		            <when test="searchCondition == 0">
						AND ID LIKE '%' || #{searchKeyword} || '%'
					</when>
		            <when test="searchCondition == 1">
						AND	NAME LIKE '%' || #{searchKeyword} || '%'
					</when>
				</choose>
			</if>
	</select>

</mapper>