반응형

 

https://extsdd.tistory.com/112

 

[Spring/eGov ] #7 스프링, 전자정부프레임워크 샘플 예제- 마이바티스(MyBatis)로 마리아 DB 연동하기 /

https://extsdd.tistory.com/102 [Spring/eGov ] #6 웹 서비스 만들기 2 / 요청 URL 파라미터 가져오기 / Debug 방법 / 디버깅 하는법 / @Model extsdd.tistory.com 자 우리가 마지막으로 했던게 사용자 요청 URL..

extsdd.tistory.com

  자 저번 시간까지 이클립스와 Maria DB를 MyBatis라는 친구로 연동을 시켰다. 아. 전에 MyBatis가 먼지 설명을 안했는데 간단하게 설명하자면 과거에 JAVA코드로 쿼리로 DB에 있는 데이터를 조회하려고 하면, 소스안에 자바코드도 껴져있고, SQL쿼리문도 껴져있고, 개판처럼 만들어 놓고 썻기때문에 관리도 안됐던 문제가 있었다. 사실 머 문제라기보단 조 불편하고 효율적이지 않았던거지!

MyBatis

 

  하지만 쿼리문과 자바 구문들을 분리해놓으면서, 자바는 자바구문 끼리, 그리고 쿼리는 xml파일에 두고 namespace로 Mapping시켜 사용하게 하는 MyBatis방식이 나왔고 xml에 IF같은 태그가 가능해지면서 쿼리문도 동적으로 변화를 줄 수 있게 됐다. 그러면서 모든 Case의 쿼리를 안짜도 되고 이렇게 Flexible하게 코드를 짤 수 있으니 그야말로 효율을 극대화한 프레임워크라고 할 수 있다. 코드를 보면 머 iBatis도 있고 MyBatis도 있는데 iBatis는 아파치랑 붙어먹을때 쓰던 프레임워크고 구글로 넘어오면서 Mybatis를 쓰게 됐다고만 알고 있으면 될 것 같다.

 

  잔말 그만하고, 일단 MyBatis로 이클립스랑 마리아DB랑 연동이 안 된 사람은 위 포스팅으로 가서 설정을 하고오자. 다 된 사람이라면 이제 본격적으로 시작해보자.

1. 데이터 조회 구조 파악하기.

 

  자. 내가 웹 서비스에대해서 아무것도 모르고 회사에 와서 스프링 하세요! 했을때 완전 No Base인 상태에서 코드들을 따라갔을때 너무 복잡하게 느껴졌었다. 이게 왜 이렇게 되고, 이 코드가 어디랑 연관이 있고.. 거대한 숲에 혼자 떨어져서 내가 어디서 뭘하는지 모르는 그런 기분이었다.

 

  이제 일을 하다보니 스프링 구조에대해서 어느정도 윤곽이 잡혔고, 이제는 하늘에서 숲을 내려다 보듯이 구조와 흐름이 보이기 시작했다. 처음부터 내가 이런 윤곽을 알고 했으면 더 수월했을텐데, 이렇게 초보자들이 볼 수 있게 정리된 글들이 없었다 ㅠㅠ.. 그래서 내가 정리했다.! 초보자 시점에서 전체 윤곽을 그린 모습을!

 

  좀 어려울 수도 있는제 한번 흐름만 파악해보자.

 

 

 

  와..! 엄청 어렵고 복잡하다. 난생 웹서비스를 처음해보는 나는 이런 전체의 모습이 아닌 코드를 한줄한줄 따라가면서 고대 문자 해석하듯이 했을때는 얼마나 어려웠을까 생각해보길 바란다..ㅠㅠ

 

  어렵게 보이지만 스프링 웹 서비스의 구조는 딱 저렇다. 저기서 크게 벗어나지 않는다. 저기서 한개의 기능을 만들면 이제 복붙이고, 저 구조만 지켜지면 뭐든지 할 수 있다. 그러니까 포기하지 말고 따라오길 바란다.

 

  1 . 자 1번 박스는 스프링 프로젝트라고 생각하면 된다. 저기 16번 박스에 있는 DB를 제외하면 다 스프링 프로젝트 내의 소스로 돌리는 것이다. 1번은 별거 없다. 제일 큰 구조부터 접근해보기 위해서 번호를 넣어봤다 ㅎㅎ

Controller / 컨트롤러

 

  2. 아까까진 ice breaking이었고 여기서부터 진짜 시작이다.자 Controller 이름만 봐도 뭔가 파박! 떠오른다. 뭔가 조작하고 제어하고, 뭔가..! 뭔가를 수행하는넘! 맞다 Controller는 business(Biz) 적인 로직을 처리한다. Biz 로직이 머냐구!? 말그대로 사람이 이해할만한 "동작" 정도로 해석하면 될 꺼같은데 이런거다. 컴퓨터는 뭔가 데이터를 삽입, 삭제, 수정, 조회, 머 이런 원초적인 기능밖에 못하는데 컴퓨터가 아닌 우리 사람입장에서 기능이란, 뭔가 고객 데이터를 조회하거나, 게시판의 글 목록들을 불러오거나, 게시글을 클릭했을때 그 글을 보여줘! 처럼 사람이 이해할만한 "기능" 이라고 생각하면 되는 것이다. 좀 감이 왔나? 다시 정리하면 우리 인간들에게 기능다운 기능이란 삽입,삭제 뭐 이런 재미없는 것들을 말하는게 아니라, 그런 조회, 삽입, 삭제등 이런 컴퓨터의 기능들을 이용해 우리 인간세계게에서 통용될 수 있는 그런 기능을 작성하는 것이다. 예를들면 할머니한테 할머니! 제가 DB에서 Select 기능을 수행했어요! 하면 할머니는 뭔 개소리냐? 하고 반문할꺼지만, 할머니! 제가 어떤 예약이 있는지 조회했어요!! 한다면 할머니가 이해할 것이다. 차이점이 느껴지나..! 컴퓨터에는 "예약을 조회한다"는 기능이 없다! 예약정보가 어디있는지, 이걸 조회할지 삭제할지 이런건 다 인간이 정한거고 이 기능을 만들기 위한 로직을 Business 로직이라고 한다.

 

  자 Controller의 결론을 말하자면, 기능을 작성하는 곳이다! 이정도로 이해하면 될 것 같고, 로직은 그냥 짜면 된다 if어쩌고~ 아니면 저쩌고~ 쭈르륵 작성하는데 DB에서 데이터를 가져와야할꺼 아냐? 그 데이터를 가지고 오기 위한 놈이 Service(서비스)라는 놈이다. 예전 포스팅에서도 이 서비스란 놈을 좀 설명했는데, 특정 기능들의 데이터를 서리하는 집합체라고 생각하면 된다. 더 raw하게 써논 설명을 보고 싶다면

https://extsdd.tistory.com/99

 

[Spring/eGov] #3 스프링 기본 구조 / Sample 예제 프로젝트 분석 / 원리 / 전자정부프레임워크 / 컨트롤�

 

extsdd.tistory.com

  위 포스팅 중간쯤에 서비스란 무엇인가 이걸 참조하면 된다. 아무튼 서비스가 실제로 데이터들을 불러오기 위한 객체인데, 우리 Controller에서 필요한 정보들을 조회하기 위한 서비스를 미리 호출해놓고 쓴다.

 

  3. 자 3번 박스를 보면 그 컨트롤러의 실제 예시 코드를 캡쳐해 놓은 것이다. 구조를 보면 컨트롤러 fwdService를 미리 호출해놓고 5번 박스를 보면 그 객체로 8번 박스의 함수를 호출해서 데이터를 조회하는 것을 볼 수 있다. 조회된 데이터들은 17번에 있는 resultList에 담기고 그 밑으로 이 조회된 데이터를 기준으로 Biz 로직을 작성하면 하나의 기능이 되는 것이다.

 

  4. 자 보면 컨트롤러에 fwdService가 선언되었다. 앞으로 이 Controller에선 fedService가 할 수 있는 기능을 이용할 수 있게된다. 필요한 서비스를 이렇게 불러놓으면 되는 것이다.

 

  5. 4번에서 선언한 서비스를 실제로 로직에서 불러와 사용한 것이다.

 

  6. 그 서비스는 service 패키지 경로안에 ~~~~Service.java 형식으로 파일이 있을 것이다. 4번 박스처럼 fwdService라면 FwdService.java 라는 파일로 만들어 놨을 것이다.

 

  7. 이게 이 Service 파일의 구조인데, 보면 함수 이름정도만 선언되어있다.. 즉, 여기서 로직이 작성되진 않는다. 서비스에서 처리하는 로직은 ServiceImpl.java에서 구현된다. Impl 는 Implement정도로 해석하면되고, 말그대로 구현이다.

 

  8. 보면 아까 7번 서비스에서 선언된 기능을 Biz 로직단에서 호출하는 것을 볼 수 있다. 아까 말했듯이 이 구현은 ServiceImple.java에서 구현된다고 했으니까 계속 알아보자.

 

  9. 자 ServiceImpl.java로 오면 크게 구조가 DAO라는 친구가 선언되어 있다. 이건 나중에 알아보도록하고 실제 코드를 보자

 

  10. 자 실제로 serviceImpl.java를 와보자.보면 아까 우리가 7,8번에서 언급한 함수가 여기도 선언되어있다. 맞다 Interface로 선언된 친구다. 그 실제 로직을 보자

 

  11 .바로 이거다 DAO라는 친구를 이용해 selectList를 해오는 것이다. 보면 fwd.selectTargetUrl 이라는 쿼리를 수행하라고 되어있는데, fwd는 xml파일의 namespace를 말하는 것이고, 이 네임스페이스로가면 selectTargetUrl이라는 쿼리문이 있을것이다.

DAO (Data Access Object)

 

  먼저 DAO라는 친구를 알고가야한다. 발음은 "다오"라고 부른다. 개귀엽다 ㅎㅎ.. 암튼 이친구가 뭐하는 역할이냐면,DB와 COnnection을 이용해 데이터를 가져와 주는 놈이다. 과거에 코딩을 좀 해본사람이라면 Java 소스안에서 Connection을 맽고 조회하고, Connection을 끝고,, 이런 불필요한 코드들이 아주 많았고, 한번 조회할때마다 이 커넥션을 게속 작성해야해서 너무 불편했다. 하지만 이제 DAO라는 친구에서 조회할꺼면 select, 삽입할꺼면 insert 등.. 함수만 치면 이런 커넥션 알아서 맺고 조회하면 알아서 끝고 다해주는 친구다. 세부 구현은 어떻게됐는지 몰라도 된다. 특급 개발자들이 다 잘 구현해 놓았을테니까 ㅎㅎ 우리는 사용만 하면된다.

 

  12-1. 저 쿼리문을 MyBatis라는 저 fwd.selectTargetUrl이라는 문구를 보고 어디에 있는 파일에서 어떤 구문을 조회할지 Mapping해주는 역할을 해준다.

 

  12-2. 그럼 이 마이바티스를 통해서 fwd네임스페이스니 fwdSql.xml이란 파일을 뒤져서 거기있는 selectTragerUrl이란 쿼리문을 찾아온다.

 

13. 그게바로 이 13번 박스에 있는 id로 매핑시켜 찾아오는것이다.

 

  14. 자 그럼 마이바티스가 어떤 쿼리를 조회할지도 알아낸 것이다.

 

  15. 이제 본젹적으로 아까 말했던 DB랑 Connection을 맺는 DAO라는 친구를 통해, 마이바티스에서 넘겨받은 쿼리 구문들을 본격적으로 조회한다.

 

  16. DAO를 통해 DB에 접속한 단계이다. Connection이 맺어지면 아까 받은 쿼리들을 조회하고 그 결과를 DAO가 다시 가져온다. 그럼 역순으로 다시 11번 박스를 보면 그 조회 결과가 리턴되고, 이 리턴받은 데이터들은 8번 박스에 나온 저 함수에서 리턴되 결국 17번 박스에 있는 변수로 들어가게 되는것이다.

 

  17. 결국 조회된 데이터가 resultList라는 변수에 들어가고 우린 그걸 사용하면 된다.

 

결론 : 기능은 ~Controller.java, ~Service.java, ~ServiceImpl.java, ~VO.java(필요하다면), ~Sql.xml 가 세트로 다닌다고 생각하면 된다. 이렇게 한사이클 돌았는데, 나머지도 보면 다~~똑같다, 이해가 안돼도 되니 느낌만 알고 가도록 하자

2. CommonDAO.java 추가

 

  자 먼저 공통적으로 DB에서 커넥션을 맺어줄 DAO를 만들어보자!

 

 

  자 cmmn 패키지에 오른쪽마우스를 눌러 NEW-Class를 눌러주고 패키지 경로를 하나 만들어주자.

 

 

  자 패키지 경로명에 .dao를 추가해서 만들어주자.

 

 

  만들어진 dao 패키지에 새 클래스를 만들어주자.

 

 

  뚜둔~ 이름은 CommonDAO로 만들어주자!

 

 

  보면 dao 패키지 밑에 CommonDAO.java 파일이 생겼다! 열어보자!

 

 

귀여운 파일이 생겼다. 소스를 넣어 생기를 불어넣어주자.

package cpservice.cmmn.dao;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Repository;

import egovframework.rte.psl.dataaccess.EgovAbstractMapper;

@Repository("CommonDAO")
public class CommonDAO extends EgovAbstractMapper {

	/**
	 * 입력 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId -  입력 처리 SQL mapping 쿼리 ID
	 *
	 * @return DBMS가 지원하는 경우 insert 적용 결과 count
	 */
	public int insert(String queryId) {
		return super.getSqlSession().insert(queryId);
	}

	/**
	 * 입력 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId -  입력 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 입력 처리 SQL mapping 입력 데이터를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 *
	 * @return DBMS가 지원하는 경우 insert 적용 결과 count
	 */
	public int insert(String queryId, Object parameterObject) {
		return super.getSqlSession().insert(queryId, parameterObject);
	}

	/**
	 * 수정 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 수정 처리 SQL mapping 쿼리 ID
	 *
	 * @return DBMS가 지원하는 경우 update 적용 결과 count
	 */
	public int update(String queryId) {
		return super.getSqlSession().update(queryId);
	}

	/**
	 * 수정 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 수정 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 수정 처리 SQL mapping 입력 데이터(key 조건 및 변경 데이터)를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 *
	 * @return DBMS가 지원하는 경우 update 적용 결과 count
	 */
	public int update(String queryId, Object parameterObject) {
		return super.getSqlSession().update(queryId, parameterObject);
	}

	/**
	 * 삭제 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 삭제 처리 SQL mapping 쿼리 ID
	 *
	 * @return DBMS가 지원하는 경우 delete 적용 결과 count
	 */
	public int delete(String queryId) {
		return super.getSqlSession().delete(queryId);
	}

	/**
	 * 삭제 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 삭제 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 삭제 처리 SQL mapping 입력 데이터(일반적으로 key 조건)를  세팅한 파라메터 객체(보통 VO 또는 Map)
	 *
	 * @return DBMS가 지원하는 경우 delete 적용 결과 count
	 */
	public int delete(String queryId, Object parameterObject) {
		return super.getSqlSession().delete(queryId, parameterObject);
	}

	//CHECKSTYLE:OFF
	/**
	 * 명명규칙에 맞춰 selectOne()로 변경한다.
	 * @deprecated select() 메소드로 대체
	 * 
	 * @see EgovAbstractMapper.selectOne()
	 */
	//CHECKSTYLE:ON
	@Deprecated
	public Object selectByPk(String queryId, Object parameterObject) {
		return super.getSqlSession().selectOne(queryId, parameterObject);
	}

	/**
	 * 단건조회 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
	 *
	 * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)
	 */
	public <T> T selectOne(String queryId) {
		return super.getSqlSession().selectOne(queryId);
	}

	/**
	 * 단건조회 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 단건 조회 처리 SQL mapping 입력 데이터(key)를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 *
	 * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)
	 */
	public <T> T selectOne(String queryId, Object parameterObject) {
		return super.getSqlSession().selectOne(queryId, parameterObject);
	}

	/**
	 * 결과 목록을 Map 을 변환한다.
	 * 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다.
	 *
	 * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
	 * @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용
	 *
	 * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map
	 */
	public <K, V> Map<K, V> selectMap(String queryId, String mapKey) {
		return super.getSqlSession().selectMap(queryId, mapKey);
	}

	/**
	 * 결과 목록을 Map 을 변환한다.
	 * 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다.
	 *
	 * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 맵 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 * @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용
	 *
	 * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map
	 */
	public <K, V> Map<K, V> selectMap(String queryId, Object parameterObject, String mapKey) {
		return super.getSqlSession().selectMap(queryId, parameterObject, mapKey);
	}

	/**
	 * 결과 목록을 Map 을 변환한다.
	 * 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다.
	 *
	 * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 맵 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 * @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용
	 * @param rowBounds - 특정 개수 만큼의 레코드를 건너띄게 함
	 *
	 * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map
	 */
	public <K, V> Map<K, V> selectMap(String queryId, Object parameterObject, String mapKey, RowBounds rowBounds) {
		return super.getSqlSession().selectMap(queryId, parameterObject, mapKey, rowBounds);
	}

	//CHECKSTYLE:OFF
	/**
	 * 명명규칙에 맞춰 selectList()로 변경한다.
	 * 
	 * @see EgovAbstractMapper.selectList()
	 * @deprecated List<?> 메소드로 대체
	 */
	//CHECKSTYLE:ON
	@Deprecated
	public List<?> list(String queryId, Object parameterObject) {
		return super.getSqlSession().selectList(queryId, parameterObject);
	}

	/**
	 * 리스트 조회 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
	 *
	 * @return 결과 List 객체 - SQL mapping 파일에서 지정한  resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
	 */
	public <E> List<E> selectList(String queryId) {
		return super.getSqlSession().selectList(queryId);
	}

	/**
	 * 리스트 조회 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 *
	 * @return 결과 List 객체 - SQL mapping 파일에서 지정한  resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
	 */
	public <E> List<E> selectList(String queryId, Object parameterObject) {
		return super.getSqlSession().selectList(queryId, parameterObject);
	}

	/**
	 * 리스트 조회 처리 SQL mapping 을 실행한다.
	 *
	 * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 * @param rowBounds - 특정 개수 만큼의 레코드를 건너띄게 함
	 *
	 * @return 결과 List 객체 - SQL mapping 파일에서 지정한  resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
	 */
	public <E> List<E> selectList(String queryId, Object parameterObject, RowBounds rowBounds) {
		return super.getSqlSession().selectList(queryId, parameterObject, rowBounds);
	}
	
	/**
     * @description   Map 으로 리스트를 조회한다. 단 페이징 로직을 수행한다.
     */
    /*public <E>List<E> selectListWithPaging(String id ,CmMultiVO vo) {
    	MappedStatement ms = super.getSqlSession().getConfiguration().getMappedStatement(id);
    	
    	
		//전체 ROW Counting을 위해 기존 SQLMap 객체를 카피하고 PaginationStatementInterceptor에서 excute하기전에 쿼리를 조작함
		if(!super.getSqlSession().getConfiguration().hasStatement(id+"$$_TOTCNT___$$")){
			MappedStatement.Builder msBuilder = new MappedStatement.Builder(
					ms.getConfiguration(), id+"$$_TOTCNT___$$", ms.getSqlSource(),
					ms.getSqlCommandType());
			
			msBuilder.resource(ms.getResource());
			msBuilder.fetchSize(ms.getFetchSize());
			msBuilder.statementType(ms.getStatementType());
			msBuilder.keyGenerator(ms.getKeyGenerator());
			if (null != ms.getKeyProperties()) {
				for (String keyProperty : ms.getKeyProperties()) {
					msBuilder.keyProperty(keyProperty);
				}
			}
			msBuilder.timeout(ms.getTimeout());
			msBuilder.parameterMap(ms.getParameterMap());
			ResultMap.Builder rmBuilder = new ResultMap.Builder(ms.getConfiguration(), ms.getId()+"$$_TOTCNTMAP___$$", Integer.class, new ArrayList<ResultMapping>());
			ArrayList<ResultMap> rsList = new ArrayList<ResultMap>();
			rsList.add(rmBuilder.build());
			msBuilder.resultMaps(rsList);
			msBuilder.cache(ms.getCache());
			
			synchronized(super.getSqlSession().getConfiguration()) {
				super.getSqlSession().getConfiguration().addMappedStatement(msBuilder.build());
			}

		}
		
		//신규로 생성한 sql을 실행, 실행 시 PaginationStatementInterceptor sql을 조작함
		int totCnt = super.getSqlSession().selectOne(id+"$$_TOTCNT___$$", vo);
		RowBounds rowBounds = null;
		if(vo.getPaginationInfo() != null){
			vo.getPaginationInfo().setTotalRecordCount(totCnt);
			rowBounds = new RowBounds(vo.getPaginationInfo().getFirstRecordIndex(), vo.getPaginationInfo().getRecordCountPerPage());
		}else{
			rowBounds = new RowBounds();
		}


		//실행 시 PaginationStatementInterceptor sql을 조작함
		List<E> resultList = super.getSqlSession().selectList(id, vo, rowBounds);
		
		
		return resultList;
    }*/
    
	/**
	 * 부분 범위 리스트 조회 처리 SQL mapping 을 실행한다.
	 * (부분 범위 - pageIndex 와 pageSize 기반으로 현재 부분 범위 조회를 위한 skipResults, maxResults 를 계산하여 ibatis 호출)
	 *
	 * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
	 * @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map)
	 * @param pageIndex - 현재 페이지 번호
	 * @param pageSize - 한 페이지 조회 수(pageSize)
	 *
	 * @return 부분 범위 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 부분 범위 결과 객체(보통 VO 또는 Map) List
	 */
	public List<?> listWithPaging(String queryId, Object parameterObject, int pageIndex, int pageSize) {
		int skipResults = pageIndex * pageSize;
		//int maxResults = (pageIndex * pageSize) + pageSize;

		RowBounds rowBounds = new RowBounds(skipResults, pageSize);

		return super.getSqlSession().selectList(queryId, parameterObject, rowBounds);
	}

	/**
	 * SQL 조회 결과를 ResultHandler를 이용해서 출력한다.
	 * ResultHandler를 상속해 구현한 커스텀 핸들러의 handleResult() 메서드에 따라 실행된다.
	 *
	 * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID
	 * @param handler - 조회 결과를 제어하기 위해 구현한 ResultHandler
	 * @return
	 *
	 * @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List
	 */
	public void listToOutUsingResultHandler(String queryId, ResultHandler handler) {
		super.getSqlSession().select(queryId, handler);
	}
	
}

저 소스덩어리를 이어서 CommonDAO.java에 넣어주자.

 

 

  넣으면 이런식으로 쭉~ 코드들이 들어갈텐데 저장을 눌러주자. 여기 내용들은 머 이해할 필요까진 없다. 이미 Mapper 역할을 할 EgovAbstractMapper를 상속받아 만들어진 것이기 때문에 그냥 아~ 여기 데이터에 접근해 조회, 삭제, 삽입, 변경 하는 함수들이 들어가는 구나 ~ 정도만 알고있으면 된다.

3. Service 추가

 

 

 

  자 이제 내 DB에서 데이터를 읽어올껀데 그렇게 하기위한 파일들을 작성해보자 먼저 service 부터 선언할껀데 위 service 패키지를 오른쪽마우스 눌러 New버튼 클릭 후 Class를 눌러주자. 그리고 앞으로 파일 생성할 일이 많으니 클래스를 만들라~ 하면 이정도는 외워두길 바란다.

 

 

  자 이름은 FwdService로 정해주고 Finish를 눌러주장!

 

 

  그럼 빈 파일이 생성된다.

아래 코드를 복붙하고 저장해주자.

package cpservice.fwd.service;

import java.util.List;

import egovframework.rte.psl.dataaccess.util.EgovMap;

public interface FwdService {
	/**
	 * URL 조회
	 * @param FwdVO 검색조건
	 * @return List<?> URL 목록
	 */
	List<EgovMap> selectTargetUrl(FwdVO vo);
}

 

 

 

  짜잔 서비스가 생겼다~ 이제 저 서비스에 있는 selectTargetUrl 기능을 구현해보자.

 

4. ServiceImpl 구현

 

 

 

  자 ServiceImpl.java를 만들껀데 다른점이라면 Impl파일은 서비스 패키지가 아니라 impl 패키지에 추가한다는 점이다. 꼭.! 경로 헷살리지 않도록 하자, 만약 service 캐키지 밑에 impl패키지가 없으면 만들어라, 만드는거 New누르고 Package누르면 만들 수 있다. 암트 다시돌아와서 impl 패키지를 오른쪽마우스 누르고 New-Class를 눌러 만들어주자. 이제 파일 만드는 것은 설명안해두 되겠지..!?

 

 

  파일 이름은 FwdServiceImpl로 만들어주자

 

 

 짜잔..! 생겼다..!

 

 

  개 귀여운 파일이 생겼다. 내용을 넣어주자

package cpservice.fwd.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import cpservice.cmmn.dao.CommonDAO;
import cpservice.fwd.service.FwdService;
import cpservice.fwd.service.FwdVO;
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
import egovframework.rte.psl.dataaccess.util.EgovMap;

@Service("fwdService")
public class FwdServiceImpl extends EgovAbstractServiceImpl implements FwdService {

	/** CommonDAO */
	// TODO mybatis 사용
	@Resource(name = "CommonDAO")
    private CommonDAO dao;
	
	/**
	 * 요청에 맞는 URL을 조회하는 쿼리
	 */
	@Override
	public List<EgovMap> selectTargetUrl(FwdVO vo) {
		// TODO Auto-generated method stub
		return dao.selectList("fwd.selectTargetUrl", vo);
	}

}

 

  코드 설명을 간단히 해보자면 이 서비스의 selectTargerUrl 함수를 돌리면 selectTargetUrl 쿼리를 조회해서 뱉어주는 역할을한다.

5. fwdSql.xml 작성

 

  자 이제 쿼리문이 작성될 fwdSql.xml을 작성할 것이다.

 

 

  sqlmap 폴더에 폴더를 하나 만들어주자.

 

 

  폴더 이름은 fwd로 정해주자!

 

 

  만들어진 fwd 폴더에 XML파일을 추가해주자. New - Other 클릭!

 

 

  XML을 검색해주고 밑에 XML File을 눌러 NEXT!

 

 

 

  파일명은 fwd.xml로 추가!

 

 

  자 fwd폴더 밑에 fwd.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="fwd">

	<select id="selectTargetUrl" parameterType="cpservice.fwd.service.FwdVO" resultType="egovMap">
		/** selectTagetUrl (fwdSql.xml) 마스터코드 목록 조회*/
		SELECT PM.SEQ_NO
			,PM.URL_STR
			,PM.DISC_STR
			,PM.USE_YN
		FROM prd_mst PM
		WHERE PM.SEQ_NO = #{reqParam}

		 
	</select>
	
</mapper>

 

  통째로 복붙하고 저장하자

 

 

  1. 소스를 좀 살펴보자. 먼저 1번 박스가 네임스페이스다. 자바 소스에서 쿼리를 불러올때 fwd.selectTargetUrl 이라는쿼리를 불러올때 앞에 fwd가 이 네임스페이스다. 긍까 네임스페이스가 Fwd인 파일에있는 selectTargetUrl이란 쿼리를 찾아오겠다~ 이말이다.

 

  2. 2번 박스를 보면 id="selectTargetUrl"로 되어있는데 1번에서 설명과 마찬가지로 해당 쿼리의 고유 ID다, 이 쿼리를 불러오기위해선 저 ID를 호출해야하는 것이다.

 

  3. 이건 파라미터 타입이다. 이 쿼리를 실행하기전에 여기다 객체를 집어 넣을 수 있다. 넣어서 뭐하냐고?!! 아주 중요한 질문인데, 자 만약에 넣을 수 없다면, 저 쿼리를 봤을때 5번 박스가 있는 Where 절에 SEQ_NO를 1일때, 2일때, 3일때 똑같은 쿼리를 여러번 만들어 줘야하는데 #{reqParam} 이란 변수명이 보이는가!?, 저 파라미터로 가져온 FwdVO안에 있는 저 변수명을 가지고 올 수 있는 것이다. 이 쿼리를 요청할때 함수 구문에 VO를 넣어주는 것이 보일텐데, 여기서 그 VO에 넣어져 있는 값을 사용할 수 있는 것이다. 만약에 reqParam에 1이 들어있으면 WHERE PM.SEQ_NO = 1 로 쿼리가 설정되고, reqParam에 2가 들어오면 WHERE PM.SEQ_NO가 2로 셋팅되는식으로, 쿼리문은 하나인데 들어오는 값들에 의해서 쿼리가 동적으로 변화하면서 아주 유연한 쿼링이 가능케하는 것이다. 이게 바로 MyBatis의 강점이라고 할 수 있다.

 

  4. 이건 조회하고나서 어떤 데이터 형으로 뱉어줄지다. 머 String이라고 하면 문자열로 나가는등, 원하는 타입으로 선언하면 된다. 하지만, DB특성사 조회하면 여러 컬럼의 형태로 조회되기 때문에 Map형태로 뽑아줘야한다. 이 전자정부프레임워크에는 egovMap이라는 데이터형이 만들어져 있는데 이 Map을 쓰는게 가장 사용하기 좋다.

 

  5. #{변수명} 이라고 쓰면 3번 박스에서 선언된 VO를 읽어와 그 VO에 들어온 정보들을 쓸 수 있다.

6. Controller.java 수정

 

  자 이제 데이터를 조회할 준비는 다됐고 실제 Biz 로직단에서 반영되도록 소스를 수정해주자!

 

 

  자 저번까지 작성한 컨트롤러의 코드를 보면 그냥 하드코딩이 되어있다. 들어오는 파라미터가 1이면 네이버를, 2면 다음, 3이면 구글 이렇게 값자체가 소스에 박혀있어 나중에 사후 관리측면에서 문제가 되는 소스들이다.

 

  이걸 이제 DB에서 불러오는걸로 바꿔보자 아예 통째로 소스를 부어 넣어주자.

 

package cpservice.fwd.web;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import cpservice.fwd.service.FwdService;
import cpservice.fwd.service.FwdVO;
import egovframework.rte.psl.dataaccess.util.EgovMap;

@Controller
public class FwdController {

	/** 고객관리 서비스 */
	@Resource(name = "fwdService")
	private FwdService fwdService;
	
	@RequestMapping(value = "/reqUrl.do")
	public String selectReqUrl(@ModelAttribute("searchVO") FwdVO searchVO, ModelMap model) throws Exception {
		
		List<EgovMap> resultList = fwdService.selectTargetUrl(searchVO);
		
		String URL = (String) resultList.get(0).get("urlStr");
		
		return "redirect:http://"+URL;
		
	}
	
}

 

  자 이소스로 복붙하고 저장하자.

 

 

  소스를 살펴보자면

 

  1. fwd 관련 쿼리를 사용할 것임으로 fwdService를 호출해주자.

2. 이 호출한 서비스에서 selectTargetUrl 함수를 돌려 쿼리를 실행하주고, 그걸 resultList에 넣어주자. 자 또하나 보자면 함수의 파라미터로 searchVO를 넣어줬는데. 이건 사용자가 이 reqUrl.do를 요청할때 넣어준 데이터들이 들어있는 객체다. 이 VO를 쿼리돌리는 저함수에 넣어주면 분명 저 FwdVO안에 있는 reqParam이라는 사용자가 요청한 값도 받아올 것이다.

 

  3. 자 쿼리를 돌려 조회된 결과가 resultList인데 사실 이 쿼리는 여러행이 나오지 않는다. reqParam에 매칭되는 목적지 URL은 하나이기 때문에 단건 조회인데, 그럼 또 다른 함수를 타야하는데 보통 다건 조회가 많으니 그냥 List형태로 받아오도록했다.. 그래서 resultList.get(0)을 통해서 맨 첫번째 결과를 가져와 get("urlStr")을 통해서 조회한 쿼리에서 urlStr 칼럼을 가져오겠다는 것이다.

 

  4. 마지막으로 redirect://http:// 와 URL을 붙혀 리턴해주면 DB를 기반으로 조회하는 포워딩 시스템이 완성된다!

7. 결과 확인

 

 

  자 이제 서버를 한번 Clean뒤 Run을 해보면 서비스가 동작할텐데 오류없이 실행되면 잘 된거다. 다시 http://localhost:8080/reqUrl.do?reqParam=3이렇게 테스트로 조회를해보고 끝에 reqParam= 뒤에 값을 1,2,3등으로 변경하면서 엔터를 눌러봐라. 만약 각 DB에 넣은 정보에 맞는 페이지를 호출하면 잘 된거다.

 

  혹시 오류가 나는사람들은 다음 포스팅에 할 Debug과정을 통해서 한번 값들이 어떻게 이동하는지 살펴보도록 하자.

 

 

#스프링 #전자정부프레임워크 #마리아DB #이클립스 #마이바티스 #컨트롤러 #DAO #원리 #구조 #MariaDB #ByBatis #Controller

 

 

반응형
  1. HAVY 2021.01.12 15:37

    글 잘보고 있습니다 덕분에 스프링 이해가 잘 됩니다.
    한 가지 부탁이 있습니다.
    우클릭 및 드래그가 되지 않아 긴 코드를 복붙하지 못하고 일일히 타이핑하고 있습니다.
    본문들의 내용을 보니 그걸 일부러 설정하신게 아닌것 같은데 괜찮으시면 혹시 복사 방지를 풀어주실수 있으신가 하고 조심스럽게 여쭤봅니다...

  2. HAVY 2021.01.14 09:48

    중복 댓글 죄송합니다...또한 fwdSql.xml 생성하는 법이 나오지 않은 것 같습니다. 오류가 계속 생겨서 디버깅해보니 프레임워크에서 mariaDB의 정보를 못읽어오는듯 하여 글을 다시보니 fwdSql.xml에서 뭔가 연동을 시키는 것 같아서 댓글 남겨봅니다!

  3. ratta 2021.01.27 11:43

    잘따라가다가 fwdSql.xml 에 관한 사항이 없어 난항을 겪고 있습니다. 해당 부분에 대해 알려주실 수 있을까요? ㅠㅠ

    • ratta 2021.01.27 15:57

      필요없는 난항이였군요 결국 경로를 *.xml 이기에 fwd,xml 이건 fwdSql.xml이건이 문제가 아니였네요 해결했습니다 ㅎㅎ..

    • ratta 2021.01.27 15:57

      필요없는 난항이였군요 결국 경로를 *.xml 이기에 fwd,xml 이건 fwdSql.xml이건이 문제가 아니였네요 해결했습니다 ㅎㅎ..

  4. sss 2021.06.30 16:25

    자바 처음인데 전자정부 하게 되어 혼란스럽다가, 설명 여러번 읽으니 조금 씩 이해가되는 듯 합니다 ㅎㅎ감사합니다 !

반응형

 

https://extsdd.tistory.com/100

 

[Spring/eGov] #4 스프링 Sample 기본 예제 프로젝트, 패키지 이름 바꾸기 / 파일 찾기

 

extsdd.tistory.com

 

  저번 시간에 드디어 예제 프로젝트의 정체성을 완전히 내걸로 만들어놨다 ㅎㅎ이제 진짜 내프로젝트다. 이제 진짜 간단한 웹서비스를 만들어 볼껀데, 만드려는 서비스는 웹페이지를 포워딩 시켜주는 서비스 이다. 포워딩이란 다른곳으로 안내해준다는 건데, 사용자가 특정 URL로 접근하면 사용자가 가진 데이터를 확인해서 어디로 보내줘야할지 서버가 판단해주는 역할을 수행할 예정이다. 잔말 말고 컨트롤러를 추가해보자!!

 

1. Controller 추가

 

 

 

  일단 저번에 우리가 이 포워딩 기능을 담당하는 패키지가 fwd(fowarding)라고 정해놓았고 전 글들을 읽으면 알겠지만 컨트롤러 파일은 web에 위치해 있다. 따라서 1번에 있는 cpservice.fwd.web 디렉토리에 2번 New를 눌러 3번 Class를 생성해주자.

 

 

 

  별거 없다. 1번에 기능+Controller의 이름을 설정한다. 나는 forwading 기능을 수행하는 Controller이기 때문에 FwdController로 명명했다. 완료되면 딴거 손델 필요 없이 Finish를 눌러주자.

 

 

  ㅡㅡ... 찐따같은 파일이 하나 생겼다...음.. 지금까지 보던것고 다르게 간지가 하나도 안난다..기본적인 컨트롤러의 꼴을 잡아보자.

 

  먼저 이 FwdController 자바 파일은 컨트롤러의 역할을 수행할 것이기 때문에 서버가 서블릿한테 내가 컨트롤러라는 것을 알려야한다. 그러기 위해선 저번시간에 말했던 @ 모양의 어노테이션을 이용해 알린다고 했다. 한번 추가해보자

 

 

  망해따 벌써 오류가 뜬다.. 하지만 아니다. 저 빨간 줄이뜬 Controller라는 글자위에 마우스를 올려두고 한 1~2초를 기다려보자.

 

 

  이런 창이 나타난다. 그렇다 이클립스는 오류가 발생했을때 자기가 해결 할 수 있는만한것은 여려가지 방법으로 저렇게 추천을 해준다. 위 오류는 그거다. 그냥 @Controller만 써놓으면 컴퓨터가 모른다는 것이다. 그럼 저기 빨간 네모친 해결방안을 눌러보자.

 

 

  그럼 저 컨트롤러에 대한 정보들이 Import되는 것을 볼 수 있다. 그렇다. 컴퓨터가 알아먹을 수 있게 쟤에 대한 정보를 우리 컨트롤러에서 사용할 수 있도록 불러오자는 뜻이다. 저 org.springframework.stereotype.Controller 파일을 여기서도 사용하겠단 뜻이다. 그럼 저 @Controller가 뭔지 어떤놈이지 알아먹을 수 있단 소리로 이해하면 된다.

 

  저렇게 @Controller를 컨트롤러 클래스에 붙여놓음으로써 이제 서블릿은 사용자의 요청이 들어왔을때 여기서도 뒤지게 된다 ㅎㅎ 자. 이제 컨트롤러는 만들었고 이제 기능을 진짜로 만들어보자!!

 

  위에서 말했든 만들어볼 기능은 어떤 데이터를 사용자가 주면 그거에 따라서 서버가 알맞은 페이지를 띄어주는 기능이다. 자 그럼.. 일단 먼저 선행되어야 하는게. 사용자가 데이터를 줄때 이 데이터를 어떻게 넘겨주고, 서버에서 그걸 어떻게 받느냐는 것이다.

VO = Value Object (데이터 주머니)

 

  자 스프링에서 자료를 주고받고하는 대표적인 개념이다 브이오!! 한국말로 값을 가진 객체다!! 이게 머냐면은, 음.........구식 방식부터 생각해보자. 고객 검색 기능을 수행한다고 할때 최초에 사용자가 고객을 검색하면 이름, 연락처, 주소 등 3가지의 정보를 조회했다고 해보자. 과거에는 이 값들을 다 코드에 쳐서 달고 다녔다.

 

  통신기술이 발달함에 따라, 더 많은 정보들을 처리하게 되고, 예전시스템으로 어떤 기능을 처리하는데 200개의 변수를 담고 있다면.. 생각만해도 개 노가다일꺼 같다는 생각이 든다.. 그리고 이 고객정보 데이터를 한번만 가지고 가는것도 아니고 연계기능들을 수행하면서 계속 달고다니는데 그럴수록 문제는 더 심해진다.

 

  그래서 나온게 바로 VO다! 값들을 가진 객체!! 근데 이게 모든 데이터를 VO라는 데이터 주머니에 다 때려 박는게 아니고, 그 컨트롤러가 취급하는 정보들끼리 나눠놓는 것이다. 자 봐라, 고객정보를 처리하는 컨트롤러가 있고, 예약정보를 처리하는 컨트롤러가 있다고하면 여기서 VO는 몇개 일까? 2개다! (죽어도 2개여야하는 것은 아니다. 같이 쓸 수도 있고, 공통VO도 있고 하니까..)

 

 

  위 사진처럼 각 컨트롤러마다 필요한 공통정보들이 들어가 있을것이다. 저렇게 기능단위로 다 묶어놓으면 예약을 처리할때 저 VO만 가지고 댕기면 예약처리하는곳 어디서든 저 VO객체 하나만 넘기면 되는것이다. ㅎㅎ 쉽게 말하면 각 컨트롤러에서 사용하는 데이터들을 각각 모아놓은게 VO라고 보면 된다.

 

  나는 FwdController에서 취급할 데이터로는 고객이 요청할때 숫자 데이터를 넣어줄껀데 그데이터를 담고있는 VO를 지금 만들어보자.

 

 

  내가 FwdController에서 사용 할 VO다.... 기능이 너무 간단해서 사용자가 요청하는 데이터 한개만 담고 있을 VO다 .. 간지는 안나지만 따라하기엔 쉬울것이다. 이제 진짜 VO를 만들어보자.

 

 

  우리가 컨트롤러.java 파일을 생성했던 것 처럼 cpservice.fwd.service 패키지에 FwdVO.java를 추가해준다. 그리고 더블클릭하여 코드를보자!... 역시 간지가 안난다 빨리 채워보자.

package cpservice.fwd.service;

import java.io.Serializable;
import org.apache.commons.lang3.builder.ToStringBuilder;

public class FwdVO implements Serializable{


	/** reqParam */
	private int reqParam;

	public int getReqParam() {
		return reqParam;
	}

	public void setReqParam(int reqParam) {
		this.reqParam = reqParam;
	}


	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}
	
}

 

  해당 내용을 복붙해준다. 만약 프로젝트 이름이 다르다면 그것만 수정해주면 된다.

 

 

  소스를 복붙하고, 저기 FwdVO에 마우스를 올리면 Add generated serial version ID 버튼이 있자. 버튼을 눌러 UID를 할당시키자. serialVersionUID란 같은 클래스인지 판별할때 쓰이는데 나중에 프로그램이 변하거나 할때 프로젝트가 안깨질 확률이 높아진다. 눌러서 추가하자.

 

 

  자 UID를 추가해서 serialVersionUID가 생성된 것을 볼 수 있다. 근데 저건 사실 필요없고 이제 VO에 담길 실제 데이터를 보자. 나는 진짜 딱 한 변수만 VO에 담았다. 혹시 다른사람 더 추가하고 싶은게 있으면 1번꼴로 계속 밑에 써내려가면 된다. 2번 박스는 VO에 한번만 작성되면 되는거라서 신경이 크게 안쓰인다. 머냐면은 VO.toString() 함수를 돌리면 VO내부에 있는 key 와 Value들이 쭈르륵 나와주게 하는 함수이다. 보통 로그데이터를 뽑거나할때 많이 쓰인다.

 

  다시 1번 박스를 보면 VO의 한 데이터는 3가지 구성으로 되어 있다 먼저 자료 선언이 있다. 나는 private int reqParam으로 선언해놨고 그 밑에 get, set이 붙은 함수들이 있다. 이건 약속이다 VO는 데이터 주머니기 때문에 데이터를 set하고 다시 가져갈 수 있도록 get이 있어야한다. 한변수당 이 두개 함수는 무조건 와야하는 것이다. 만약 없으면 오류가 난다.

 

자 여기까지 했으면 ReqParam이라는 하나의 데이터를 가지고 있는 주머니인 FwdVO를 생성했다. 이제 데이터 주고받을 주머니도 만들어 놨으니 진짜!! 컨트롤러에서 기능을 구현해보자!

 

@Request Mapping

 

package cpservice.fwd.web;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import cpservice.fwd.service.FwdVO;

@Controller
public class FwdController {

	@RequestMapping(value = "/reqUrl.do")
	public String selectSampleList(@ModelAttribute("searchVO") FwdVO searchVO, ModelMap model) throws Exception {

		return "redirect:http://www.naver.com";
		
	}
	
}

  자 다시 FwdController.java로 돌아와서 위 코드를 넣어주자! 그리고 코드를 분석해보자.

 

 

  새로 생긴거 위주로 보면 1번은 뭐 이제 살짝 느꼇을꺼다..크게 뭐 중요한건 아니라는걸... 어차피 소스 추가하면 이클립스가 다 자동으로 추가하기도 해주고, 없으면 넣으라고 알려도 주니까. 암튼 저 임포트 파일들은 아래 소스코드를 돌리는데 필요한 객체들을 다 가져와 놓은 것이라고 볼 수 있다.

 

  2번 박스를 보면 핵심이다. @RequestMapping 어노테이션이 붙으면 이건 서버에서 Servlet이 받아들일 URL주소를 정의할 수 있다! 나는 reqUrl.do 라고 정의해놨는데 기존에는 localhost:8080/reqUrl.do 주소를 쳐도 서버는 저게 뭔지 알 수 없었지만 이걸 추가하는 순간 서버는 localhost:8080/reqUrl.do를 요청하면 아래 구문들을 수행하게 된다!! 이런식으로 서버에 요청들을 여기 등록해놓을 수 있는것이다. 물론 경로형태로도 등록할 수 있다. localhost:8080/tm/rs/rm/reqUrl.do 이런식으로 세분화 시킬수도 있다는 말이당 ㅎㅎ 요기다 자기가 원하는 URL을 정의하면 된다. 나는 URL을 요청하는 작업을 구현할 것이기 때문에 reqUrl.do 로 지었당.

 

  3번 박스를 보면 함수이름은 selectReqUrl이고 그뒤가 살짝 어려울 수 있을텐데 설명을 들으면 그나마 이해가 갈 것이다. 자 처음부터 @modelAttribute("searchVO" FwdVO searchVO, ModelMap model) 이 구분부터 보면 이 요청이 오면 FwdVO라는 데이터주머니에 담아서 searchVO라는 이름으로 이 함수 내부에서 사용할 것이다. 그리고 model이라는 것을 만들어놨다가. 로직을 처하면서 여기다가 사용자가 볼 화면으로 보내줄 데이터들을 모아놓을 것이다~ 이정도 의미로 해석하면 되고, throws Exception 구문은 만약 에러가 발생할시 작동하는 함수인데 보통 서버 Log에 해당 사항을 기록한다.

 

  마지막 4번 보면 함수 내부에 별다른 로직은 없고 바로 return이 되는데, 기능을 해석해보면 사용자가 localhost:8080/reqUrl.do 이 URL로 접속하면 다시 naver로 포워딩 시켜주는 기능을 수행하게 되는 것이다. ㅎㅎㅎ

 

테스트

 

  자 이제 잘 작동하는지 모두 저장하고 서버를 작동시키자! 여러번 해봤으니 이제 따로 설명은 Pass..!

localhost:8080/reqUrl.do를 인터넷창에 입력해보자!

 

 

  뚜둔..! 분명 localhost 머시기 주소를 치고 들어갔지만 네이버 화면이 떳다!! 내가 만든 서버가 작동한 순간이다 .. 감동 짝짝짝.. 일단 오늘 여기까지하고.. 너무 졸려서 자러가야겠다..

 

#스프링 #Spring #전자정부프레임워크 #웹서비스 #만들기 #컨트롤러 #VO #생성 #다른 #URL #포워딩 #Controller

 

반응형
  1. 익명 2021.01.04 14:57

    비밀댓글입니다

  2. 익명 2021.01.28 13:21

    비밀댓글입니다

반응형

 

https://extsdd.tistory.com/98

 

[Spring/eGov] #2 아파치 톰캣 설치 및 스프링 프로젝트 연동 / 셈플 예제 / WAS 구동 / 이클립스-톰캣 ��

저번시간까지 스프링 예제에 대해서 알아보았다. 이젠 이걸 실제로 구동을 시켜야 함으로 아파치 톰캣 8.0 위에 올릴 예정이다. 혹여나 아직도 아파치 톰캣에대한 개념이 잡히지 않았다면 https://

extsdd.tistory.com

 

  자 우리가 저번시간까지 전자정부프레임워크에서 만들어놓은 기본 예제를 실행시켰다. 일단. 이프로젝트가 저번에 실행시켜서 보아하니 간단한 게시판 웹 페이지를 구현해 놓은 것같다.

 

  이제 우리가 웹 서비스를 만들꺼니 당연히 구조를 알아야한다. 하지만 나도 어릴때부터 컴퓨터를 공부했지만, 아무것도 모르는 노베이스 상태에서 컴퓨터 전문가들이 하는 클래스니 객체니, VO니 DAO니 MVC니 이런 개념들 글로만 읽어봤자 아무소용이 없었다. 귀에 하나도 안들어오다가 결국 이해하게된 시점은 내가 직점 해보고 만들어보면서다. 작은 기능단위의 개념을 이해하면서 점차 넓혀 나가는 방식이 프로그래밍을 이해하는데 좋다.

 

  나는 비전공자들도 웹 서비스를 이해할 수 있는 것이 목적이기 때문에 MVC니 이런 큰 개념보다는 당장 눈에 보이는 것들 위주로 설명을 할 예정이다. 나도 처음 프로젝트를 생성했을때 아니 빈 깡통 만들었는데 무슨 파일이 이렇게 많고... 한파일에 수백, 수천줄이 이미 코딩되어있고.. 이 것들이 다 뭘 의미하는지 몰라서 자괴감을 느꼈었다. 하지만 이번부턴 그런거 느낄 시간도 없이 빠르게 진행해보자.

 

 

  Look! 봐라 일단 좌측 프로젝트 익스플로어 창에 내 프로젝트를 보자. 이미 호기심 많은 분들은 이것저것 디렉토리를 눌러보며 수많은 파일을 보며 한숨을 쉬엇테지만. 저것들 다 나중에 알아도 되는 것들이다. 이미 날고 기는 개발자들이 수많은 고민을 거쳐 만들어 놓은 파일이니. 우리가 뭐 이건 어떻고 저건 어떻고 할 시간조차 필요가 없다. 그분들을 믿고 우린 우리할껄 하자.

 

  자 아무것도 만지지말고 1번 폴더를 눌러서 그 하위 폴더를 다 펼쳐주자. 다만 저 사진에나온 cmm 폴더는 열어볼 필요 없다. 왜냐? cmm이 common 즉 "공통"의 약어이다. 저기 폴더는 우리 프로젝트에서 공통적으로 쓰이는 기능들을 구현해 놓은 이다. 공통 기능..! 자 이름만 들어도 살짝 만들기 어려운게 느껴지지 않나..? 지금 우린 한개기능 만드는것도 힘든데 서비스 전체에서 작동시킬 공통적인 기능들을 집대성한 공통기능..! 맞다. 이것도 위 문단에서 말했다시피 잘하시는 분들이 다 구현해 놓았다 ^-^ 열어보지도 말고 그냥 일단 넘어가자

 

  궁금한 사람들을 위해 간단하게 설명해주자면 프로젝트에 있는 모든 컨트롤러에 전역으로 적용되는 initBind를 정의하거나, 예외상황이 생겼을때 어떻게 할지를 전역으로 설정하거나, 게시판같이 페이지를 넘어가는 기능등 cmm 즉 공통기능답게 서비스 "전체"에 적용되는 부분을 관장한다. 여긴 몰라도 된다. 나중에 코드를 볼 줄 알면 쓱 읽으면 알게 되니까!

 

  자 이제 겁먹지 말라고 3개 문단에 나눠서 말했으니 이제 본격적으로 예제를 분석해보자. 2번 박스에 있는 EgovSampleController.java를 보자!

 

 

Camel 표기법

 

  자 일단 대소문자가 섞여잇는데 대문자가 나올때마다 띄어쓰기라고 생각하면 된다. Egov Sample Controller.java 라고 생각하면된다. 파일명이나 변수명에 띄어쓰기가 안되는데, 그냥 소문자로만 이어쓰면 Egovsamplecontroller.java 로..사실 단어 단위로 구분해낼 수가없어 암호문이 되버린다. 그래서 띄어쓰기를 표현하기위해 띄어쓰기마다 첫글자를 대문자로 작성한다. 이 표기법을 낙타 등에 혹처럼 들어갔다 나왔다 반복한다해서 Camel 표기법이라도 한다.

 

EgovSampleController.java

 

 

  자 일단 읽어보자. Egov는 이거 전자정부프레임워크의 앞글자를 딴거고 Sample은 우리가 만든 샘플 예제정도 되는거 같고. Controller..! 대박 Cmm 패키지 폴더에는 어려운 글자들만 보이다가 여기와보니 컨트롤러라는 아는 단어가 있다! 살짝 자신감이 생긴다. 컨트롤러..? 뭔가 조작을 하는가보네..?

 

 

  속한 패키지 디렉토리 이름부터 봐라. web이다.. 맞다 여기가 제일 중심이다. 뭔가 처리해주고 판단해주고 두뇌같은 역할을 한다. 이 간단한 프로젝트에 사용자들이 요청하는 기능들에 대해서 어떻게 수행하면 되는지가 요기 정의된다.

 

  앞으로 사용자가 요청이 들어왔을때 그 요청을 어떻게 처리하라!! 라고 정의하는 곳을 Controller라고 부를 것이다. 여기서 Controller에대한 개념을 조금 알고 가길 바란다.

컨트롤러(Controller)란 무엇인가.

 

 

 

  컨트롤러는 하나만 있는건 아니고 큰 기능 단위로 있다. 우린 예제 프로젝트라 걍 뭐..걍 컨트롤러라고 부르기 간지가 안나니까 Sample이라고 이름이라도 붙혀서 뭔가.. 아..컴퓨터는 Sample이란 단어 잘 안쓰는데 ㅎㅎ... 이거 사람이 만든거구나.. 인간적인 냄새라도 나라고해서 EgovSampleController지만 실제 스프링 프로젝트들을 보면 위와 같이 킨 기능 단위로 컨트롤러를 만든다.

 

  예약 조회, 삽입, 삭제, 수정 등 예약에 관한 모든것은 예약 Controller가 관리하고 그 파일에 다 명시를 하는거다. (물론 한글명으로 Controller를 만들지는 않고 뭐 RsmController.java 정도로 만든다). 또 고객에 대한 모든 기능은 고객 Controller에 담아둔다. 자이제 Controller에 대한 개념은 잡혔을 것이다. 말 그대로 기능이 어떻게 작동할지 조작을 제어하는 곳 정도로 생각하면 된다.

 

 

 

  그럼 service에 있는 애들은 머야 ㅡㅡ 서비스..? 뭔가 코딩이 아니어도 현실세계에서 서비스라고 하면 뭔가 보이지 않는 무엇을 해주는..? 이정도로 알고있을텐데 맞다 . 여기 서비스에 있는 파일들은 저기 web 패키지에 Controller가 일 할 수 있도록 도와주는 쩌리들이 모여있다. 많이 드러나지는 않아서 활약이 크게는 안느껴지는 친구들이다. 바로 서비스부터 들어가면 어려우니까 Controller의 코드부터 분석해보자!

 

 

 

  1. 자 package 머시기라고 써져있다. 여기 볼꺼없다. 그냥 이 파일이 속해있는 패키디 디렉토리 경로라고 보면 된다. 우측 패키지 익스플로어를 보면 저 경로에 파일이 위치해 있는 것을 알 수 있다. 민증 깠을때 내 집주소가 찍혀있듯이, 저 맨위에 이파일의 주속다 찍혀있는 것이다. 그렇다. package는 코딩계의 민증이라고 보면 된다. 자. 첫 번째줄은 큰 어려움 없이 통과했다. 히힣..

 

  2. import라고 써져있다. 와우! 짧다.! 하지만 좌측 +버튼을 눌러보자. 와우. x 됐다. import는 컴퓨터 좀 깔짝거리면서 프로그램 몇개 만져보면 많이 봐왔어서 익숙한데.. 밑에보니 무슨 Pagination, fdl, prt, VO..갑자기 어려운게 생겨버렸다.

 

  겁먹을거 없다. 처음부터 차근차근 이해해보자. 자 우리가 제일 자신있는 단어 import!! 맞다. 뭔가 넣어주는 거다 우리의 이 컨트롤러에(EgovSampleController.java). 근데 뭘 넣냐구..? 기능에 필요한 파일들을 넣어주는 것이다. 다시 또 묻는다. 아니 그니깐..! 뭘..! 왜 넣냐구! 한다면.. 뭐 더이상 할말이 없다.. 왜냐면.. 진짜 기능에 필요한걸 넣어주는거니까.. 하지만 나는 raw한 표현을 잘 하니 노베이스 기준으로 또 설명을 해보겠다.

 

  자.. 우리가 기능을 만들면서 숫자를 반올림하고 반내림 하는 기능이 필요하다고 가정해보자. 자 1.9를 반올림 하라하면 어떻게 할 것인가. 우린 인간이니까 그냥 딱 바로 2잖아! 하지만 컴퓨터는 그런걸 모른다. 어떻게 구현할 것인가. 반올림을 하는 인간의 사고를 그대로 컴퓨터가 이해할 수 있도록 시간을 들여 번역을 할 것인가..? 아니다. 그럴 필요가 없다.

 

  애초에 첫 포스팅부터 썻던 프레임워크가 뭔지 이해햐면된다. 우리가 프로젝트를 쉽고 빠르게 만들 수 있게 만드는 툴! 맞다. 우리가 원하는 고차원적인 예를들어 고객을 조회해 포인트를 차감하는 이런 구체적인 기능단위는 대부분의 사람들의 프로젝트에는 사용하지 않는기능이지만, 저 반올림이라는 아주 원초적인 기능은 대부분의 프로젝트에서 요구되는 기능일 것이다. 아주 기초적인 것이니까. 프레임워크란 이런 기초적인 기능들을 모아놓고 빠르게 조합해서 쓰라는 것이다.

 

  즉, 저렇게 많이쓰는 함수들은 이미 이 전자정부프레임워크라는 작업대에 다 포함되어 있는 것이고. 저 import 뒤에 나오는 경로는 그 경로에 있는 파일에 있는 기능들을 여기서도 사용하겠다!의 이미라고 보면된다.

 

  이미 import된 친구들은 이 서비스를 돌리기위해 이미 추가되어있는 것이니 손댈꺼 없다. 아~ 그냥 이 컨트롤러를 돌리는데 이런친구들을 활용하는구나~ 생각하면 된다. 다음으로 넘어가자

주석

 

 

 

  와우 씌엣..! x 됐다..! 코딩도 아닌 그냥 평문이 써져있잖아..! 20세기 코딩법인가..? 아니면 22세기 코딩법인가..? 아니다 놀라지 않아도 된다. 저건 주석이라고 한다. 뭐냐면 코드 중간중간 이코드가 무엇인지 써놓는 낙서장 같은 역할이다. 사용하는법은 이렇다 코드에 // 을 붙이면 그 뒷줄은 컴퓨터가 인식하지 못한다. 하지만 100줄을 주석처리할려면 //을 100번을 쳐야할까..? 아니다 그 그 100줄을 앞뒤로 /** 내용 ㅎㅎ **/로 감싸면 그 사이를 모두 인식 못하게 된다.

 

  저 주석을보면 저 코드가 2009년에 수정되었나보다... 아니 2019년 오타아냐?ㅡㅡ 할 수 있지만.. 2009년이면 양호한거다.. 어떤코드를 보면 2003년 주석도있고.. 그 당시 개발자의 욕..애환들도 써져있기도 하다.. 아..이거 왜 안돼.. 집에 언제가.. . 이런게 써져있는걸 처음 봤을때 잘못본줄 알았던게 생각난다..ㅋㅋ 마치 디지털 동굴 벽화를 본 느낌.. 저 주석은 읽고 이해되면 그런가보다하고 이해못하면 걍 넘어가자 ㅎㅎ

 

 

 

  1. 자 @가 붙어있다. Annotaion(어노테이션)이라고 하는데 앞으로 이 골뱅이의 의미는 "얜! 이런 성격을 가지고 있어!"라고 알려주는 거다. 즉, 이 데이터가 어떤 데이터인지 설명해주는 데이터라고 보면된다. @뒤에 Controller라고 써져 있으니. 미 밑줄 public class EgovSampleController 라는 친구는 "Controller"라는 친구야!! 라고 설명을 해주는 것이다. 이건 컴퓨터가 소스코드를 읽어올때 먼저 어노테이션부터 읽어놓고 이놈에 필요한 정보들을 미리 준비한다. 그럼 또 Controller라고? 그게 먼데? 라고 또 묻는다면 위를 다시 읽어보면 된다. 내가 계속 말한 컨트롤러에 대한 설명을 저 @Controller 라는 한줄로 컴퓨터는 아하!!! 하고 알아듣는다.

 

  2. public class EgovSampleController 이부분을 보자. 이건 java에대한 기본 지식이 있으면 저 public calss의 의미는 알것이고 비전공자분들은 저거 크게 신경 안써도 된다. 학교에서 시험볼때나 저거만지지 스프링 프로젝트 하다보면 거의 만지는일은 없다.. EgovSampleController는 이 컨트롤러의 이름이다. 이건 좌측 패키지 익스플로어에 나오는 파일명과 일치해야한다. 자 2번까지도 별거 없다. 3번으로 가자

 

 

  3. 자 이제 좀 코드다운게 나왔다. 쫄지말자 일단 첫줄 /** EgovSampleService **/ 이건 위에 말했다시피 주석이다. 밑에있는 내용이 EgovSampleService라는 친구에요 ^-^하고 알려주는 것이다. 자그럼 두번째줄 @Resource(name = "sampleService") 어..! 이거 살짝은 알아 들을 수 있을꺼 같은데..!? 그렇다 @Resource가 붙어있으니 아래 나오는 private EgovSampleService는 Resource라는 형태로 되어있는놈이다!! 이렇게 해석하면된다. 저기 name = "sampleSerivce"라고 되어있는데 짐작이 가지 않는가..? 맞다 그 Resource의 이름은 sampleService라는 놈이고 그놈이랑 연결을 시킨다라는 의미다.

 

  좀 더 나아가자면 웹 서비스가 처음 구동될때 생성된 POJO라고 불리는 함수나 상속, 구현이 없이 순수히 데이터만 가진 객체를 생성하는데 물론 그 데이터마다 name이 있다. 그 당시 만들어진것을 지금 저 Controller가 지금 매칭을 시키는 것이다. 시작하면서 만들었던 그 객체!! 우리가 지금 써야해!! 하고 Resource 어노테이션을 이용해서 연결시키는 것이다.

 

  다음줄을 보면 private EgovSampleService sampleService라고 되어있다. 자 이건 자료의 형이 EgovSampleService이면서 여기서 사용할 이름은 sampleService라고 선언하는 것이다. 물론 이 객체는 위에 Resource 어노테이션을 이용해 연결된 smapleService라는 객체의 데이터를 받았다고 생각하면 된다.

 

서비스(Service)란 무엇인가

 

  자.. 위에서 본 3번 박스.. 요약하자면 지금 sample이란 이름의 service를 데리고 온거나! 컨트롤러에! 그게 뭐냐면 앞으로 컨트롤러 내부에서 sample에서 정의된 모든 기능들을 쓸 수 있다는 얘기!! 자.. 여기서 뭔 소린가 멘탈나간 사람들을 위해서 그림으로 정리해봤다.

 

 

 

  자 .. 이상하긴 하겠지만 군대에 이걸 대입해보자. 자 컨트롤러란 공통된 기능들의 집합인데 이걸 군대로 치면 통신부대, 전차부대, 포병부대, 공병부대 이렇게 각 역할들로 묶인 집단으로 생각할 수 있다. 사용자들이 웹 페이지에 요청을 어떻게 처리할지 Controller에 정의하듯이, 통신부대도 상급부대에서 명령이 내려오면 어떻게 할지는 통신부대 내부에서 처리한다.

 

  자! 다시 부대얘기로 돌아와서 사령부에서 "지금 A~B구간의 통신망 개통이 가능하니?" 라는 요청을 한다면 이 통신부대에서는 요청을 처리해야할 것 아닌가? 그럼 요청은 어떻게 처리할까? 그냥 부대원들 모여서 야 ㅎㅎ 개통 가능할까..? ㅎㅎ 투표할까..? 아님 발표하고싶은사람있어..? ㅎㅎ 이렇게 오합지졸로 결론을 도출할까? 아니다.

 

  그 통신부대에는 운용과장이 전술,전략에대해 판단하고, 군수과장은 출동에 가용한 차량은 몇대나 되는지, 식수는 몇명인지 등 각 역할별로 본인들의 "기능"들이 있을 것이다.

 

  더 세부적으로 들어가면 운용과장은 1. 지형을 판단하여 통신망 개통이 가능한지의 판단. 2. 적의 예상 침투로를 판단, 3. 지형과 기상을 판단 등 여러가지 판단을 내릴 수 있고 이건 인사과장이나 군수과장의 임무가 아니고 운용과장만이 주로 해야하는 일종의 기능들인 것이다.

 

  이제 좀 감이 잡혔는지 모르겠다. 즉 서비스라는 것은 특정 기능들을 하기위해 필요한 객체들을 불러와 놓은것이다. 서비스 이름이 SampleService라고 해놔서 샘플 기능을해..? ㅡㅡ 라고 좀 이해가 안된다 생각할 수도 있지만.. 머 마땅히 붙힐 이름이 없어서 저렇게 붙혔을 것이다.. 샘플 프로젝트라 머..아무 기능이 없는데 뭔서비스라고 지어 ㅡㅡ 라고 생각해서 아마 그냥 프로젝트의 이름을 따와서 SampleService라고 지어놨을 것이다.

 

 

 

  자 그럼 어떤 서비스들을 꺼내놨는지 보자.

 

 

  1. sampleService란다. 이건 우리가 예제로 만들어져 있는 서비스다. 그 상세 기능은 저 파일안에 정의되어 이씅며 저 서비스가 하는내용으론 게시판의 글을 조회하고, 수정하고, 목록을 가져오는 아주 범생이같은 일을 처리해주는 서비스다.

 

  2. propertiesService는 파일에 찾아봐도 없을 것이다. 바로 이건 살짝 깊숙한 곳에서 불러왔기 때문이다. 여기에대해서 설명하면 좋은데 그럼 또 너무 길어진다. 우린 쓸일이 없으니, 분량을 위해 더이상 알아보지말고 어떤 놈인지만 알고 넘어가자. 바로 페이지의 크기가 정의되어 있다.

 

 

  context-properties.xml에 정의되어 있는데 아니..!갑자기 잘나가다 왜 갑자기 이딴게 튀어나와!!! 할 수 있지만. 일단 넘어가자. 설명하면 좀 길다. 일단 이 서비스는 게시판 목록에대한 정보를 가져오는 서비스라고 생각하자.

 

  3. 자 얘도 더욱이 알필요 없다. 말그대로 Validator 즉, 유효성을 검증해주는 친구인데 말만들어도 재미없다..그냥 시스템을 탄탄하게 해주는 놈이라고 생각하고 넘어가자.

 

URL Request Mapping

 

 

 

  자 이제 쭈르륵 내려보면 저 뭉텅이의 꼴들이 계속 나올텐데 이게 가장 중요하다 사실 위에 말했던거 이해하면 좋은거고 이해못해도 상관없다. 어차피 저거다 복붙해서 이름만 바꾸고 크게 중요하지 않다 초보자 입장에서는..

 

  이제 알아볼 것은 이제 진짜 요청을 어떻게 처리시킬지를 정의해두고 있다. 주석을 보면 함수가 어떤기능을 하는지를 정의해놨다 긍 목록을 조회하는 함수라고 한다.

 

  1. 자 어노테이션에 RequestMapping이 붙었다. 제일 중요한 녀석이다. 사용자가 글목록을 조회할때 http://localhost:8080/egovSampleList.do 라는 URL이 요청될텐데 웹 서비스는 저 egovSampleList.do 라는 요청을 누가 처리하는지 찾아낸다. 근데 모든 함수를 전수조사하면 답이 없으니 저 RequestMapping이라는 어노테이션이 붙은 친구들중에서만 찾아낸다. 만약 저걸 처리해주는 함수를 만나면 실행시키는 것이다!

 

  2. 그래서 함수의 이름도 요청의 이름과 동일하다

 

  3. 글을 어떻게 불러오고 어떻게 처리할지 구체적인 비지니스적인 로직이 여기 작성된다. 일단 우린 큰틀부터 잡을 것이기 때문에 여기에 그런 것들이 적힌다는 것만 알고 넘어가자

 

  4. "sample/egovSampleList"를 반환헀다. 결국 3번에서 처리한 결과를 반환한것이다. 이제 그 결과가 사용자가 보는 화면단에 나타날 것이다.

 

 

  여기까지 알아본게 바로 뒷단 로직인것이다. 전체적으로 한번 보자. 컨트롤러는 함수이름으로 보지말고 RequestMapping 값이 어떤 URL인지 보는게 더 편하다. 사용자도 저 주소를 치고 들어가니까말이다. 아 그리고 요청 URL의 끝은 .do를 쓰는데 그냥 그런가보다 해라. do someting!! 뭔가를 수행해라!!의 의미로써 우리가 아는 do의 의미랑 같다. 이렇게 붙인 이유는 다른 Servlet과 충돌을 막기위해 아무거나 바꾸긴 해야하는데... 그냥 적당한걸로 바꿨다고...

 

 

 

  자 정리해보자. 우리의 기본 컨트롤러인 EgovSampleController는 게시글 관련기능, 페이지 목록, 유효성을 검증해주는 3개의 서비스를 호출해놨고 이 컨트롤러에서는 글 조회, 등록화면 조회, 글 수정화면 조회, 글 수정, 삭제 등 5가지의 기능을 수행하는 컨트롤러다!

 

  만약 사용자가 http://localhost:8080/ + 저 기능에대한 주소 를 요청하면 이 컨트롤러가 위에 정해진 로직대로 기능을 수행할 수 있다. 오늘은 여기까지 뒷단 로직의 일부를 알아보았다.

 

 

 

  자 정리하면 딱 이거다.

 

  1. 사용자는 크롬이던 익스플로러든 웹 화면을 보고 글을 쓰기위해 "등록" 버튼을 누른다

  2. 등록 버튼이 눌리면 등록 화면을 호출해주는 URL을 호출한다.

  3. 그 URL은 addSample.do 이다.

  4. 스프링 서비스에서는 Servlet이란놈이 저 addSample.do요청이 들어오면 누가처리해!!!!!!!!소리를 지르다 RequestMapping 어노테이션을 뒤져보니 EgovSampleController가 해준다는 것을 알아낸다.

  5. 찾아냈으니 그 요청에대한 비지니스 로직을 실행한다

  6. 결과로 sample/egovSampleRegister.jsp를 반환했다. 그럼 사용자한테 이 화면을 보여주면 되는거다!

  7. WAS가 5번에서 넘어온 정보들을 sample/egovSampleRegister.jsp에 뿌려 조립을해서 그 결과를 사용자에게 보여준다!!!!!!!!!!!

 

  하!!!!!!!!! 이거 포스팅 작성하는데 한 4시간 걸린 것같다...일단 큰 개념을 잡았으니, 다음시간에..간단한 요청처리를 하나 만들어보자..ㅠㅠ 힘드러

 

 

#스프링 #Spring #전자정부프레임워크 #기본구조 #샘플예제 #예제 #프로젝트 #분석 #원리 #컨트롤러 #Controller #서비스 #Service

 

 

반응형
  1. codeNug.... 2021.01.07 17:38

    아... 스프링에 대한 기본 개념없이 전자정부프레임웍을 만지다가 한계를 느끼고 다시 시작해보려고 찾아들어왔는데...
    넘나 정성글에 재밌게 따라갔네요ㅋㅋㅋㅋ 내 마음이랑 똑같잖아....?! 전부 정독하고있습니다....!

  2. c린이 2021.01.14 10:56

    글 절대 지우지 말아주세요,,ㅠㅠㅠ 감사합니다ㅜㅡㅠ

  3. 호야 2021.01.18 21:03

    소중한정보감사합니다 ㅠ

  4. 디디 2021.11.22 20:57

    이해가 쏙쏙됩니다~!!! 좋은 글 넘 감사드려요!!!

  5. WJ.Lee 2021.11.23 15:50 신고

    잘 정리해 주셔서 감사합니다.

+ Recent posts