
오늘 드디어 구현하고 싶었던 기능을 만들어냈다. '플래너'를 만드는 것이기 때문에 우리가 흔히 사용하는 달력을 만들어서 일정을 추가하면 해당 일에 일정이 나타나도록 할까 했지만 그것보다 위처럼 나오되 1주일 단위가 아닌 하루 단위로 나오게 하고 싶었다. 그래서 오늘 날짜에 맞춰 일정이 나오도록 하는 것 어렵지 않았으나 비동기 통신을 이용해서 어제 일정을 가지고 오려고 하니 조금 어려웠다. 그래서 그 비동기 통신을 이용해서 어제 일정을 가져오는 기능을 구현한 과정을 포스팅해보려고 한다.
로그인을 하고 메인 화면으로 들어오면 memberService에서 localDate로 현재 날짜를 가져오고 String으로 형변환한 다음에 쿼리문에 사용할 변수로 넣어준다.(날짜인데 String으로 변환해준 이유는 MEMO 테이블에서 begin이라는 컬럼으로 일정을 조회하는데 처음에는 Date 타입을 썼다가 VARCHAR2 타입으로 바꿔줬다. 그래서 String으로 형변환한 것이다.)

오늘 날짜 기준으로 2022-05-26일에 맞는 일정을 위처럼 보여준다. 오늘 하고 싶었던 것은 앞에서 말했듯이 노란색으로 칠한 부분에 원하는 날짜를 입력하고 보기 버튼을 누르면 해당 날짜 일정을 비동기 통신으로 보여주는 것이었다.
이전에 회원가입을 구현할 때, 아이디 중복 체크 기능을 구현하느라 비동기 통신으로 값을 가져와서 사용한 적이 있었다. 그때는 값을 가지고 와서 비교하는 게 끝이었는데 이번에는 데이터를 가지고와 VIEW에 뿌려줘야 하니 이전 작업에 추가되는 부분이 존재했다.
대략적인 로직을 보면
main.jsp에서 ajax로 get 요청을 한다. → 컨트롤러에서 ajax의 요청을 받아서 메서드를 실행하고 결과 값을 main.jsp가 아닌 other.jsp로 넘겨준다. → other.jsp에 우리가 원하는 값이 출력될 것이고 other.jsp를 main.jsp에 넣어주면 된다.
이 정도만 정리해도 어느 정도 파악이 가능할 거 같다. 그럼 코드를 보면 완전히 이해가 가능할 것이다.
먼저 main.jsp에서 ajax로 구현할 부분을 보자. 아래 코드는 main.jsp의 일부분이다.
○ main.jsp
<script type="text/javascript">
function otherDay(){
var id = $("#id").val();
var begin = $("#begin1").val();
$.ajax({
type:"GET",
url:"/planners/${begin}",
data: {"id":id, "begin": begin},
dataType: "text",
success:function(result){ // 통신에 성공하면
$("#frm").css("display","none"); // id=frm인 <div>를 안보이게 none으로 바꿔주고
$("#frm2").css("display","block"); // id=frm2인 <div>가 나타나도록 block으로 바꿨다.
$("#frm2").html(result);
},
error:function(request,status,error){ // 통신에 실패하면 왜 그런지 알기 위해 넣은 코드
alert("code:" +request.status + "\n"+"message:" +request.responseText + "\n" + "error:" + error);
}
});
}
</script>
<div class="wrapper">
<h1>What To Do Today !</h1><br>
<form method="get">
<input type="date" name="begin1" id="begin1" value="${begin}"/> <button type="button" onclick="otherDay()" >보기</button>
<input type="hidden" name="id" id="id" value="${id}"/>
</form>
<div class="content" name="frm" id="frm" style="border: 1px solid gray ">
<label for="begin">Date</label><br>
<span name="begin" id="begin">${begin}</span><br>
<hr>
<c:if test="${memoList.size() eq 0}">
등록된 일정이 없습니다.
</c:if>
<c:if test="${memoList.size() ne 0}">
<c:forEach items="${memoList}" var="memo">
<a onclick="location.href='/planners/${memo.planno}/Detail'" >
${memo.title}</a>   ${memo.content}<br>
<hr>
</c:forEach>
</c:if>
<div style="position:relative; width:300px; height: 60px;">
<div style="position : absolute; clear:left; float:right; width:300px; height:50px; left:0; bottom:0px;">
<input type="button" value="+" onclick="location.href='/planners/write'"
class="w3-button w3-circle w3-deep-orange w3-right">
</div>
</div>
</div>
<div class="content" id="frm2" name="frm2" style="display:none ;border: 1px solid gray ">
</div>
</div>
○ plannerController.java
@GetMapping("/{begin}")
public String planner(Memo memo, Model model){
List<Memo> memoList = memoService.getOtherMemo(memo);
model.addAttribute("memoList",memoList);
model.addAttribute("begin",memo.getBegin());
return "/planner/other";
}
begin1 값과 id 값을 /planners/${begin}으로 넘겨줬다. 그럼 이 파라미터를 가지고 쿼리문을 작성하고 조회한 결과 값을 List타입으로 반환해줄 것이다. 그 List를 main.jsp가 아닌 other.jsp로 넘겨주면 우리가 보고 싶은 날짜의 일정을 other.jsp가 표현하고 있다.
○ other.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<style type="text/css">
.wrapper {
display: grid;
place-items: center;
}
.content {
font-family: system-ui, serif;
font-size: 1rem;
padding: 5px;
}
</style>
<label for="begin">Date</label><br>
<span name="begin" id="begin">${begin}</span><br>
<hr>
<c:if test="${memoList.size() eq 0}">
등록된 일정이 없습니다.
</c:if>
<c:if test="${memoList.size() ne 0}">
<c:forEach items="${memoList}" var="memo">
<a onclick="location.href='/planners/${memo.planno}/Detail'" >
${memo.title}</a>   ${memo.content}<br>
<hr>
</c:forEach>
</c:if>
<div style="position:relative; width:300px; height: 60px;">
<div style="position : absolute; clear:left; float:right; width:300px; height:50px; left:0; bottom:0px;">
<input type="button" value="+" onclick="location.href='/planners/write'"
class="w3-button w3-circle w3-deep-orange w3-right">
</div>
</div>
원하는 데이터를 표현하고 있는 other.jsp를 main.jsp의 id="frm2"인 <div> 태그에 넣어주면 아래처럼 해당 부분만 바뀌어서 나온다.

사실 지금처럼 우회를 해서 구현한 이유가 있다. 처음에는 우회하지 않고 바로 main.jsp로 가져와서 데이터를 뿌려주고 싶었지만 ajax로 받아온 데이터는 JSTL에서 사용하는 것이 불가능하다는 정보를 접하고 나서 여러 가지 방법을 찾아보다가 지금처럼 우회하는 방법으로 해결하게 된 것이다.
불가능한 이유는 서버의 작업 순서가 JAVA> JSTL> HTML> JavaScript 이기 때문이다. 이거 구현하면서 비동기 통신도 어느 정도 알게 되고 @ResponseBody가 왜 쓰이는지(여기서는 사용을 안 했지만) 등 공부가 된 거 같아서 기분은 좋다.
※ 추가

ajax 통신 후 200 OK라는 응답을 받았지만 success가 아닌 error로 로직이 구현되고 있었다. 아래 에러 코드가 같이 출력되고 있었는데 찾아본 결과 생각보다 간단한 이유로 통신에 실패했던 것이다.

ajax를 작성했던 곳을 보면 dataType이라는 속성이 있다. 저 속성이 넘겨주는 데이터의 형태를 알려주는 것인 줄 알고 json으로 작성했다. 에러가 나고 알아본 결과 넘겨받는 데이터의 형태를 쓰는 것이었다. json을 text로 바꿨더니 정상적으로 출력이 됐다.

혹시 같은 상황에서 고생하는 분들이 있다면 이 글이 조금은 도움이 되길 바란다.
※ 도움을 주신 분들
https://my-t-space.tistory.com/47
https://okky.kr/article/389900
'Hi Planner' 카테고리의 다른 글
[Hi Planner] @Builder 어노테이션 ( + 트러블 슈팅) (0) | 2022.06.01 |
---|---|
[Hi Planner] 메시지 가져오기(All elements are null 해결) (0) | 2022.05.29 |
[Hi Planner] login 화면 (0) | 2022.05.21 |
[intelliJ + gradle + spring boot] 오라클 연동과 마이바티스 의존성 추가 (0) | 2022.05.13 |
[intelliJ + gradle + spring boot] JSP 프로젝트 시작하기 (HiPlanner) (0) | 2022.05.13 |