실습

o[1차 프로젝트] #1 목록 출력(페이징 기법 자세히 설명드릴게요!)

원코딩 2022. 8. 5. 00:04






본격적인 프로젝트가 시작되면서
밤을 지새우는 날이 잦아졌다.
그동안 행복했던 거였다.....


미래에 나는 과거의 내가 행복했던 거라고 하겠지?


프로젝트는 실무에 가까우니까
미래의 내가 혹시 참고할 기록을 남기는게 좋겠다.


그렇게 시작된 프로젝트 일기





1. 목록 출력 - 페이징 기법


목록 출력할 때 가장 중요한건 페이징 기법(가장 어려웠음)이다.

▶ 출력하는 데이터 VO 생성
데이터 베이스의 컬럼을 VO생성하는 법은 아래에 설명되어 있다.

[JAVA/오라클] 시큐어 코딩 Getter Setter 사용법 (오라클 <> 자바 데이터형 맞추기)

웹에서 데이터를 가져올 때 변수를 사용한다. 이때 데이터 노출의 위험이 있기 때문에 변수를 감추는 과정이 필요하다. 이를 위해 자바에선 private 변수를 사용하여 캡슐화 하는데 이처럼 보안상

codingwone.tistory.com



▶ mapper생성 후 SQL 문장 작성
sql 문장 생성할 때 조건을 no의 start와 end를 입력값으로 지정해줘야 한다.
데이터가 100개 라면 목록에 100개를 전부 띄우는 것이 아니라, 10개씩 10개의 페이지를 만들어야 하니까!

<select id="videoDetailListData" resultType="VideoVO" parameterType="hashmap">
	SELECT vd_no,vd_title,vd_poster,vd_subtitle,vd_deadline,num
	FROM (SELECT vd_no,vd_title,vd_poster,vd_subtitle,vd_deadline,rownum as num
	FROM (SELECT /*+ INDEX_ASC(PK_VIDEO_DETAIL_1)*/vd_no,vd_title,vd_poster,vd_subtitle,vd_deadline
	FROM video_detail_1)) 
	WHERE vd_no BETWEEN #{start} AND #{end}
</select>


그리고 총페이지 SQL 문장을 추가로 작성해야 한다.
100개를 10개씩 출력한다면 총 페이지는 10이 된다. 이걸 CEIL 함수를 사용해서 구한다.

<select id="videoListTotalPage" resultType="int" parameterType="hashmap">
	SELECT CEIL((COUNT(*)/9.0)) FROM video_detail_1
</select>

나는 3*3의 형태로 9개씩 출력했음


▶ DAO 생성 후 오라클 getConnection , disConnection 하기
mybatis 이용하면서 소스가 매우매우 간단해졌다.
session으로 오라클 연결 >
mapper에 작성해둔 SQL문장 실행 하고 변수에 데이터 저장 >
session 반환(오라클 닫기) >
리턴 값으로 변수 >
모델에서 처리할 예정

public static List<VideoVO> videoDetailListData(Map map)
	{
		SqlSession session=null;
		List<VideoVO> list=null;
		try
		{
			session=ssf.openSession();
			list=session.selectList("videoDetailListData",map);
		}catch(Exception ex)
		{
			System.out.println("videoDetailListData : error");
			ex.printStackTrace();
		}
		finally
		{
			if(session!=null) 
			{
				session.close();
			}
		}
		return list;
	}

사실 try~catch절 생략하면 몇 줄이면 끝나지만 오류가 나면 찾을 수가 없어서 함께 작성하는게 좋다!


▶ Model (Controller) 에서 값을 어떤 화면으로 보내줄지 설정
이해하기 가장 어려웠던 부분이다.
모델은 사용자에게 받은 값과 + DB에서 가져온 값 + DB에서 가져온 데이터를 가공한 값 온갖 데이터들이 정리되고 합쳐지는 공간이다.

동시에 request의 중요성이 돋보이는 곳이기도 하다.
해당 모델은 MVC로 처리가 되어있는데 (솔직히 강사님이 만들어주셨다 ㅎㅎ)
session과 request로 데이터를 주고 받는다.

사용자에게 받은 값과 데이터에서 가져온 값을
데이터를 화면에 출력하기 위해 request.setAttribute로 jsp 파일에 넘겨준다.

페이징 기법

@Controller
public class VideoModel {
	// 강의 리스트
	@RequestMapping("video/video_list.do")
	public String video_List(HttpServletRequest request, HttpServletResponse response)
	{
		String page=request.getParameter("page");
		if(page==null)
			page="1";
		
		int curpage=Integer.parseInt(page);
		Map map=new HashMap();
		int rowSize=9;
		int start=(rowSize*curpage)-(rowSize-1);
		int end=curpage*rowSize; 
		
		
		map.put("start", start);
		map.put("end", end);
		
		List<VideoVO> list=VideoDAO.videoDetailListData(map);
		int totalPage=VideoDAO.videoListTotalPage(map);
		final int BLOCK=5;
		int startPage=((curpage-1)/BLOCK*BLOCK)+1;
		int endPage=((curpage-1)/BLOCK*BLOCK)+BLOCK;
		if(endPage>totalPage)
		{
			endPage=totalPage;
		}
		
		request.setAttribute("curpage", curpage);
		request.setAttribute("totalpage", totalPage);
		request.setAttribute("startPage", startPage);
		request.setAttribute("endPage", endPage);
		request.setAttribute("list", list);
		
		request.setAttribute("main_jsp", "../video/video_list.jsp");
		return "../main/main.jsp";
	}

1. 현재 페이지 설정

String page=request.getParameter("page");
if(page==null)
page="1";

request로 페이지 값을 가져온다.
이때 페이지를 선택하지 않으면 사용자에게 빈 화면이 노출될 수 있다.
null값이라면 1을 채워준다. (자동으로 1페이지가 보일 수 있도록)

int curpage=Integer.parseInt(page);
웹에서 받은 데이터는 '문자형'으로 되어 있기 때문에 '숫자형'데이터로 변환해준다.
지금부터 curpage는 현재 페이지이다.


2. 한 페이지당 보여줄 객체 수 설정

int rowSize=9;
row 값은 한 페이지당 객체를 몇개 보여줄지 설정하는 것이다.
나는 3*3 형태로 총 9개의 영상을 보여줄 예정이므로 9를 저장했다.

int start=(rowSize*curpage)-(rowSize-1);
int end=curpage*rowSize;
만약 1페이지라고 가정하면
start는 (9*1) - (9-8) = 9 - 8 = 1
end는 1*9 = 9
1 ~ 9 까지 총 9개의 데이터를 가져오겠다는 뜻이다.

2페이지라면
start는 (9*2) - (9-8) = 18 - 8 = 10
end는 2*9 = 18
10 ~ 18 이렇게 총 9개의 데이터를 가져온다.

map.put("start", start);
map.put("end", end);
start와 end를 map의 put 기능을 이용하여
키값과 값의 형태로 오라클 문장에 전송한다.


4. 시작 페이지와 끝 페이지 설정

위의 사진을 보면 1~7 페이지 까지 설정되어 있다.
그럼 시작 페이지는 1, 끝 페이지는 7이다.
화살 표를 다음으로 넘기면 어떻게 될까?
시작페이지는 8, 끝 페이지는 14이다.

final int BLOCK=5;
위의 사진은 BLOCK을 7로 설정했을 경우이다.
나는 5개의 페이지가 고정되어 보여지도록 할 것임으로
블록 값을 5로 설정했다.

int startPage=((curpage-1)/BLOCK*BLOCK)+1;
int endPage=((curpage-1)/BLOCK*BLOCK)+BLOCK;
1 페이지 부터 ~ 5 페이지 동안은
1 ~ 5 까지만 화면에 보여야 하기 때문에 위와 같은 식으로
시작 값과 끝 값을 고정해야 한다.

현재페이지가 1일 때 startPage는
(1 - 1) / 5*5 +1 = 0/5 *5 + 1 = 0*5 + 1 = 0*1 = 1
endPage는
(1 - 1) / 5*5 + 5 = 0/5 *5 + 5 = 0*5 + 5 = 0*1 = 5

현재페이지가 5일 때 startPage는
(5 - 1) / 5*5 +1 = 4/5 *5 +1 =0(int는 정수라서 소수점은 이하 생략) *5 +1 =0 +1 = 1
endPage는
(5 - 1) / 5*5 + 5 = 4/25 +1 =0(int는 정수라서 소수점은 이하 생략) *5 +5 = 0 + 5 = 5
* 모든 값을 0으로 곱하거나 나누면 결과 값은 0이 된다.

이처럼 현재페이지가 1 ~ 5 사이에 있다면
startPage 는 1으로 , endPage는 5으로 고정되어 있다.

현재페이지가 6일 때 startPage는
(6 - 1) / 5*5 +1 = 5/5 *5 + 1 = 1*5 + 1 = 5+1 = 6
endPage는
(6 - 1) / 5*5 + 5 = 5/5 *5 + 5 = 1*5 + 5 = 5+5 = 10

이처럼 현재페이지가 6 ~ 10 사이에 있다면
startPage 는 6으로 , endPage는 10으로 고정되어 있다.

if(endPage>totalPage)
{
endPage=totalPage;
}
총 페이지 수가 38 페이지인데, 위의 endPage는 40까지 표기된다. 그럼 사용자는 39 페이지와 40페이지에 대한 버튼은 있어도 화면은 보이지 않는 상황이 될 수 있다. 따라서 endPage가 총 페이지 수보다 크다면 총 페이지 수 만큼만 endPage 값이 설정되도록 하였다.

4. 총페이지 구하기

<select id="videoListTotalPage" resultType="int" parameterType="hashmap">
	SELECT CEIL((COUNT(*)/9.0)) FROM video_detail_1
</select>

총 페이지 = totalpage는 이렇게 CEIL 함수를 이용해서 구할 수 있다.
총 갯수를 / 출력하고자 하는 데이터 수 만큼 나눠주고
CEIL 함수로 소수점 이하 수를 무조건 올림 처리 한다.

5. 정보 전송

request.setAttribute("curpage", curpage);
request.setAttribute("totalpage", totalPage);
request.setAttribute("startPage", startPage);
request.setAttribute("endPage", endPage);
request.setAttribute("list", list);
페이지에 필요한 데이터들을 setAttribute를 이용해 키값과 데이터 값을 각각 전송한다.

request.setAttribute("main_jsp", "../video/video_list.jsp");
return "../main/main.jsp";
메인페이지에 홈 부분이 include 되어 있기 때문에
main_jsp 부분에만 화면에 출력될 수 있도록 값을 전송한다.










최종 출력 화면이다 . 밑을 보면 적용된 페이지를 확인 할수 있다. !