개발자꿈나무
SpringBoot를 이용한 mvc2 TodoList 구현 - 검색 페이징, 로그 추가 본문
사용한 기술 : Spring / SpringBoot / MyBatis / MariaDB / JSP
이용한 객체 : DTO / DAO / Service / Controller / View
현재까지 구현한 기능 : CRUD / 페이징처리 / 검색
추가로 구현이 필요한 기능 및 기술 : Log4j2 / Validation / 파일 업로드 기능 / 로그인(원래는 비회원 게시판!)
기본적인 CRUD 기능과 페이징 처리, 검색 처리까지 완료를 했었고 이후에 이틀 동안 검색 페이징에서 생겼던 이슈와 로그 추가에 대한 부분을 블로깅해보고자 한다.
대표적 이슈 : 검색을 하고 페이지를 넘겼을 때 저장된 모든 기록들이 초기화된다는 부분
우리가 해결하고자 시도했던 방법들 :
1. url에서 값이 넘어가지 않아서 자바스크립트를 통해서 강제로 값들을 넘기도록 하는 방법
2. getParam으로 값들을 하나하나 일일히 받아서 넘겨주는 방법
해결책을 찾은 방법 :
검색을 하게 되면 같은 list값을 겟매핑으로 받아서 넘겨줘야하는데 search라는 매핑을 새로해줘서 넘겨주니까 수정을 하는데도 시간이 오래 걸리고 마땅한 해결책도 생각이 나지 않았다. 메소드들을 하나하나 확인해봤는데 결국 list 메소드와 search 메소드의 내부 구현체는 동일하고 페이징 처리를 위해서 count 처리를 하는 부분만 조금 다른 것뿐이라는 걸 확인했고, void로 list메소드를 처리하고 있다는 부분을 체크해서 코드를 수정해봤다.
[수정하기 전 코드]
"search"와 "list"를 각각 다르게 매핑해줬다. 결국 같은 list페이지인데 이렇게 해주면 검색을 해주게 되면 search?write= 이런 식으로 주소가 바뀌게 되는데 굉장히 이질감이 느껴진다는 걸 깨달았다. 이렇게 각각의 컨트롤러에서 처리를 해주다 보니 값들을 받아오는게 힘들었고 list 메소드 안에 if문을 통해서 model.addAttribute를 해줬는데 이렇게 되니까 검색 조건을 우리가 처음에 설정했던 것과는 다르게 만들어야 한다는 부분이 발생했다.
@GetMapping("search")
public String search(Model model, PageRequestDTO pageRequestDTO) {
model.addAttribute("responseDTO",service.search(pageRequestDTO));
System.out.println("search 성공");
System.out.println(pageRequestDTO.getStartDate());
System.out.println(pageRequestDTO.getEndDate());
System.out.println(pageRequestDTO.getSearchContent());
return "list";
}
@GetMapping("list")
public void list(PageRequestDTO pageRequestDTO, BindingResult bindingResult, Model model) {
if(bindingResult.hasErrors()) {
pageRequestDTO = PageRequestDTO.builder().build();
}
model.addAttribute("responseDTO",service.getList(pageRequestDTO));
}
[수정 후 코드]
@GetMapping("list")
public void list(PageRequestDTO pageRequestDTO, Model model) {
model.addAttribute("responseDTO",service.getList(pageRequestDTO));
model.addAttribute("responseDTO",service.search(pageRequestDTO));
System.out.println("Paging list");
}
굳이 if문을 쓰지 않아도 그냥 list 메소드 안에 getList와 search의 메소들을 다 집어넣어도 검색이 가능하다는걸 발견했다. 이렇게 되면 위에서 만든 로직보다 검색할 수 있는 범위가 훨씬 넓어져서 더 유용하게 사용할 수 있다. 검색 조건들 중에서 날짜는 무조건 입력을 해줘야하고 나머지는 입력을 하지 않아도 검색이 되도록 로직을 만들어줬고, 검색 조건을 넣지 않았을 때는 submit이 되지 않도록 제이쿼리를 이용해서 로직을 구현했다.
<script>
$(".searchForm").submit(function () {
let startDate = document.getElementById('startDate').value;
let endDate = document.getElementById('endDate').value;
if (startDate == '') {
alert("시작 날짜를 입력하세요");
$('.startDate').focus();
return false;
}
if (endDate == '') {
alert("종료 날짜를 입력하세요");
$('.endDate').focus();
return false;
}
});
</script>
다음으로 처리해준 부분은 바로 로그처리 부분이다!
사용할 수 있는 로그들로는 log4j, logback, Slf4j, log4j2 등 다양한 프레임워크가 있는데 log4j2나 log4jdbc는 logback만 이해하면 세팅만 해주면 되는 부분이라 logback에 대해서 좀 더 공부하는 것을 목표로 하기 위해서 우리는 spring boot에서 제공하는 logback을 사용했다. 따로 dependency를 해줄 부분은 없었고, (springboot-starter 내부 라이브러리를 보면 logging 프레임이 포함되어 있는 것을 알 수 있다) logback-spring.xml 을 통해서 로그로 띄운 레벨과 패턴들, appender할 부분들을 설정해준다.
[로깅의 레벨]
⛔ Error : 예상하지 못한 심각한 문제가 발생하는 경우, 즉시 조취를 취해야 할 수준의 레벨
⚠️ Warn : 로직 상 유효성 확인, 예상 가능한 문제로 인한 예외 처리, 당장 서비스 운영에는 영향이 없지만 주의해야 할 부분
✅ Info : 운영에 참고할만한 사항, 중요한 비즈니스 프로세스가 완료됨
⚙️ Debug : 개발 단계에서 사용하며, SQL 로깅을 할 수 있음
📝 Trace : 모든 레벨에 대한 로깅이 추적되므로 개발 단계에서 사용함
예외처리를 위한 로그 클래스도 하나 만들어줬는데 @ControllerAdvice 어노테이션을 활용해서 예외가 발생하면 로그에 설정해놓은 로그 메세지를 띄울 수 있도록 만들어줬다.
(@ExceptionHandler, @ModelAttribute, @InitBinder가 적용된 메소드들에 AOP를 적용해 Controller 단에 적용하기 위한 어노테이션.
모든 @Controller에 대해 전역적으로 발생하는 예외를 잡아서 처리 가능
-> 이렇게 된다면 Controller에서 유효성 검사를 필요로 하는 곳에 @Valid 어노테이션을 붙이고, 해당 위치에서 걸리게 되면 @ControllerAdvice가 이를 잡아 처리하는 것!)
모든 예외의 상위 클래스인 Exception 클래스를 처리하도록 구현해줬지만 추가로 특정 예외들을 설정해줄 수 있다.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
//예외처리를 위한 로그 클래스
@org.springframework.web.bind.annotation.ControllerAdvice
public class ControllerAdvice {
private Logger logger = LoggerFactory.getLogger(ControllerAdvice.class);
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String exception(Exception exception) {
logger.error("Internal Server Exception: {}", exception.getMessage()); // {} 자리에 에러 메세지 뜸
return exception.getMessage();
}
}
'기술블로그' 카테고리의 다른 글
최종 프로젝트 종료 일주일 전 (1) | 2023.05.09 |
---|---|
TCP 통신을 통한 CRUD 구현 (0) | 2023.04.07 |
SpringBoot를 이용한 mvc2 TodoList 구현 (0) | 2023.03.28 |
프로그래밍 공부 2달째 되는 날 (1) | 2023.03.08 |
미니 프로젝트 - 모델 1 기반 게시판 만들기 (2) | 2023.02.24 |