자바와 jsp로 캘린더 만들기 上

부추·2022년 4월 15일
0

대충 이런 느낌의 기능이다.

전 글에서 insert한 데이터들을 마이 프로필 - 캘린더 페이지에서 확인하는 기능이다.
짤에는 지난달 전달 밖에 안보여줬지만 더 예전, 더 과거의 달력도 열람할 수 있다. 해당 날짜에 등록된 컨텐츠의 포스터가 출력되며 해당 날짜에 2개 이상 컨텐츠가 등록된다면 포스터 오른쪽 하단에 + 아이콘이 생기며 마우스 오버 및 클릭시 드롭다운 형식으로 나머지 컨텐츠들의 포스터가 보이는 기능이다.

내가 맡았던 기능은 아니었는데 어쩌다보니 내가 구현하게 됐다. 원래 담당자였던 조원은 구글 캘린더나 풀 캘린더 등의 API를 사용해서 구현하려고 했었는데 내가 생각하기에는 아무리 생각해도 API를 사용하는 의미가 없고 오히려 우리가 구현하려는 기능을 구현하지 못할 것 같아서 정말 미안하지만 내가 API 사용을 포기하자고 했다. 지금생각해도 넘 미안하군.. 어쨌든 각설하고..

자바의 calendar 클래스와 jsp의 for:each 반복문을 이용해서 구현했다. 이글을 참조해서 만들었는데 자바 부분만 이해하는데 반나절이 걸렸다. 그래도 덕분에 너무 간편하게 구현할 수 있었습니다.. 감사합니다..

원글 작성자 분은 순수히 날짜만 계산하는 DateUtil클래스를 별도로 두고, Controller와 뷰(jsp) 이렇게 세개를 적절히 활용해서 구현하셨는데 조원을 이해하기 위해 따로 주석을 많이 달아놨던 부분은 아래와 같다.

먼저 DateUtil 클래스의 일부

public Map<String, Object> today_info(DateUtil dateData) {
		Map<String, Object> today_Data = new HashMap<String, Object>();
		
		// 날짜 함수를 이용하기 위한 Calendar 클래스의 인스턴스 호출
		Calendar cal = Calendar.getInstance();
		
		// getter setter를 이용해서 지정된 연도와 월의 값이 있을 경우 캘린더 값을 초기 설정해준다
		cal.set(Integer.parseInt(dateData.getYear()), Integer.parseInt(dateData.getMonth()), 1);

		int startDay = cal.getMinimum(java.util.Calendar.DATE);
		int endDay = cal.getActualMaximum(java.util.Calendar.DAY_OF_MONTH);
		int start = cal.get(java.util.Calendar.DAY_OF_WEEK);

		// 오늘 날짜에 해당하는 연도와 월 등의 정보를 알기 위한 호출
		Calendar todayCal = Calendar.getInstance();
		
		// 연도의 표시 형식 지정
		SimpleDateFormat ysdf = new SimpleDateFormat("yyyy");
		SimpleDateFormat msdf = new SimpleDateFormat("M");

		// 현재 연도를 위에 지정한 yyyy의 형식으로 int 타입 변수에 저장
		int today_year = Integer.parseInt(ysdf.format(todayCal.getTime()));
		int today_month = Integer.parseInt(msdf.format(todayCal.getTime()));

		// 지정한 연도와 달이 있을 경우
		int search_year = Integer.parseInt(dateData.getYear());
		int search_month = Integer.parseInt(dateData.getMonth()) + 1;

		int today = -1;
		// 지정한 연도와 달이 현재 연도와 달과 일치할 경우
		if (today_year == search_year && today_month == search_month) {
			SimpleDateFormat dsdf = new SimpleDateFormat("dd");
			today = Integer.parseInt(dsdf.format(todayCal.getTime()));
		}

		search_month = search_month - 1;

		Map<String, Integer> before_after_calendar = before_after_calendar(search_year, search_month);

		today_Data.put("start", start);
		today_Data.put("startDay", startDay);
		today_Data.put("endDay", endDay);
		today_Data.put("today", today);
		today_Data.put("search_year", search_year);
		today_Data.put("search_month", search_month + 1);
		today_Data.put("before_year", before_after_calendar.get("before_year"));
		today_Data.put("before_month", before_after_calendar.get("before_month"));
		today_Data.put("after_year", before_after_calendar.get("after_year"));
		today_Data.put("after_month", before_after_calendar.get("after_month"));

		// sql문 조건 설정을 위한 시작 날짜와 끝 날짜 값 설정
		this.db_startDate = String.valueOf(search_year) + "-" + String.valueOf(search_month + 1) + "-"
				+ String.valueOf(startDay);
		this.db_endDate = String.valueOf(search_year) + "-" + String.valueOf(search_month + 1) + "-"
				+ String.valueOf(endDay);
		
		// 인자값으로 사용하기 위해 Map에 넣어준다
		today_Data.put("db_startDate", db_startDate);
		today_Data.put("db_endDate", db_endDate);
		
		return today_Data;
	}

초반에 저 db_startDate와 db_endDate의 역할이 뭔가 했는데 매퍼사용을 위해 sql문을 작성하고 실행해보면서 알게됐다.
위의 두 값이 없으면 만약에 2022년 4월 16일에 컨텐츠를 등록했다고 하더라도 모든 연/월 16일에 컨텐츠가 계속해서 출력되는 치명적인 오류가 발생한다.
db_startDate와 db_endDate의 설정으로 연/월의 조건체크가 가능한 것.

위와 같이 작성한 DateUtil 클래스는 컨트롤러에서 이렇게 사용된다.

public String calendar(Model model, HttpSession session, HttpServletRequest request, DateUtil dateData) {

		// 날짜 함수를 이용하기 위한 Calendar 클래스의 인스턴스 호출
		Calendar cal = Calendar.getInstance();

		DateUtil calendarData;

		// 따로 지정한 연도와 월이 없는경우 현재 연도와 월을 set
		if (dateData.getDate().equals("") && dateData.getMonth().equals("")) {
			dateData = new DateUtil(String.valueOf(cal.get(Calendar.YEAR)), String.valueOf(cal.get(Calendar.MONTH)),
					String.valueOf(cal.get(Calendar.DATE)), null, null);
		}

		Map<String, Object> today_info = dateData.today_info(dateData);
		List<DateUtil> dateList = new ArrayList<DateUtil>();

		String db_startDate = String.valueOf(today_info.get("db_startDate"));
		String db_endDate = String.valueOf(today_info.get("db_endDate"));

		// 본 컨텐츠 내역 불러와서 저장
		ArrayList<CalendarVO> contents_list = calenderService.selectList(mem_num, db_startDate, db_endDate, dateData);

맨 마지막 문장이 mapper실행을 위한 service 호출이다.
아래가 mapper문장인데 어쩌다보니 많이 길어졌다.

@Select(
"SELECT 
	TO_CHAR(custom_date, 'YYYY-MM-DD') custom_date, 
    contents_num, 
    contents_type, 
    poster_path 
FROM dcontents_cal 
WHERE mem_num=#{mem_num} 
	AND custom_date BETWEEN #{db_startDate} AND #{db_endDate} "
)
public ArrayList<CalendarVO> selectList(
@Param("mem_num") Integer mem_num, 
@Param("db_startDate") String db_startDate, 
@Param("db_endDate") String db_endDate, 
DateUtil dateData);

@param의 역할은 여러개의 인자를 받을 경우에 각각을 연결시켜주는 역할

1. 뷰에서 날짜 정보를 가져옴 
2-1. (특정 날짜의 달력을 열람하고 있을 경우)
해당 달력의 연/월/일의 값을 db_startDate와 db_endDate에 입력
2-2. (특정 날짜의 달력을 열람하고 있는게 아닐 경우)
오늘에 해당하는 연/월/일의 값을 db_startDate와 db_endDate에 입력
3. custom_date BETWEEN @@년 @@월 1일 AND @@년 @@월 말일 의 where절을 갖게 되는 것이다.

위의 과정을 통해 특정 달의 컨텐츠 정보만 불러올 수 있는 것이다!
(아직 달력 그리는 코드는 보지도 못했다 다음글에 이어서..)

profile
부추가 좋아요

0개의 댓글