아래 두 줄의 코드는 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(...) | 이는 일반적으로 EgovAbstractMapper나 EgovAbstractDAO에서 제공하는 메서드로, 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>
'전자정부 프레임워크 공부' 카테고리의 다른 글
전자정부 프레임워크 3.10 게시판 예제 - Mysql 연동으로 변경 2 (1) | 2025.05.19 |
---|---|
전자정부 프레임워크 3.10 게시판 예제 - Mysql 연동으로 변경 1 (0) | 2025.05.19 |
전자정부 프레임워크 3.10 - selectSampleList (0) | 2025.05.19 |
전자정부 프레임워크 3.10 - index.jsp (0) | 2025.05.19 |
전자정부프레임워크(eGovFrame)의 web.xml 설정 (0) | 2025.05.19 |