동기처리에서 비동기처리로 가는 과정

나성민·2023년 12월 4일
0

요약

기존의 동기방식으로 처리했던 CRUD를 비동기방식으로 처리해보고자 한다.
이에 따른 차이점과 구현방식을 알아보려고 한다.

비동기처리시에 주의사항

코드를 살펴보면서 비교해봅시당

기존의 동기방식

@PostMapping("/insert.do")
public String insertFLog(
		@ModelAttribute("fLog") @Validated(InsertGroup.class) flightLogVO fLog
		, Errors errors
		, RedirectAttributes redirectAttributes
) {
		String viewName = null;

		if (!errors.hasErrors()) {
			fLog.setFlId(UUID.randomUUID().toString());
			boolean success = fLogService.createLog(fLog);
			if (success) {
				redirectAttributes.addFlashAttribute("message", "일지작성이 완료되었습니다.");
				viewName = "redirect:/operate/flightlog/view.do?what=" + fLog.getFlId();
			} else {
				redirectAttributes.addFlashAttribute("message", "일지작성에 실패하였습니다.");
				viewName = "operate/flightLog/flightLogForm";
			}
		} else {
			viewName = "operate/flightLog/flightLogForm";
		}
		return viewName;
}

동기방식에서는 Validated를 통해서 유효성검사를 하고 Error를 파악하고 이를 통해서 jsp에서 오류메시지와 기존의 값을 넣어주었습니다. 또한 viewName을 작성하여서 성공여부에 따라 페이지를 이동하게 하였습니다.

비동기시에 고려할점

서버

  1. errors가 가지고 있는 에러메시지를 어떻게 화면에 보여지게 할것인가?
  2. 처리후에 어떠한 방식으로 다음 화면을 보여줄 것인가?

클라이언트

  1. 서버에 보내는 형식이 어떻게 바뀌는가?
  2. 성공, 실패시에 리턴값을 뭐로 받고 어떻게 처리할 것인가?

결과

서버

@PostMapping("/insert.do")
@ResponseBody
public ResponseEntity<Map<String, Object>> createAssignment(
		@ModelAttribute("assignment") @Validated(InsertGroup.class) AssignmentVO assignment
		, Errors errors
) {
		// 결과를 담을 변수 선언
		Map<String, Object> response = new HashMap<>();
		
		// 정상적으로 값이 들어온 경우
		if (!errors.hasErrors()) {
			// 과제번호, 등록일시는 여기서 넣어준다.
			// 과제번호 = 강의번호 + UUID
			String asNo = assignment.getAsLecNo() + UUID.randomUUID().toString().substring(0, 7);
			assignment.setAsNo(asNo);
			assignment.setAsRegTm(LocalDateTime.now());
			
			boolean success = assignmentService.create(assignment);
			
			// 추가 성공한 경우 뷰로 이동
			if (success) {
				response.put("message", "과제추가에 성공하였습니다.");
				response.put("redirectUrl", "/lecture/assignment/view.do?asNo=" + assignment.getAsNo());
				return ResponseEntity.ok().body(response);
			} else { // 추가에 실패한 경우 (서버문제)
				response.put("message", "과제추가에 실패하였습니다.");
				return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
			}
		} else { // 값이 잘못 들어온 경우
			Map<String, String> fieldErrors = new HashMap<>();
			// 잘못된 들어온 값들 무엇인지 map에 담아주기 
	        for (FieldError fieldError : errors.getFieldErrors()) {
	            fieldErrors.put(fieldError.getField(), fieldError.getDefaultMessage());
	        }
			response.put("message", "입력값이 올바르지 않습니다.");
	        response.put("fieldErrors", fieldErrors);
	        return ResponseEntity.badRequest().body(response);
		}
}

먼저 동일하게 validation을 수행한 후에 값이 잘못들어왔다면 filedErrors라는 map에다가 다 넣어주고 이를 다시 map에 넣어서 보내줄 것이다. 이 컨트롤러는 restcontroller로 값이 그대로 json방식으로 나가도록 @ResponseBody를 붙여주었다. 또한 성공시와 실패시에 그에 맞는 message와 redirectUrl을 넣어주어서 이후에 이 정보를 가지고 클라이언트측에서 처리할 수 있도록 하였다. 마지막으로 ResponseEntity를 통해서 상태값을 같이 보내서 성공(200)인지 실패(4xx, 5xx)인지를 함께 보내도록 구현하였다.

클라이언트

.on('submit', '#asForm', function(event) {
				event.preventDefault();
				var formData = $(this).serialize();
				let url = $('input[type=submit]').data('url');
				let settings = {
					url : url,
					data: formData,
					method : 'post',
					dataType : 'json',
					success : function(response) {
						if (response.message) {
							alert(response.message);
						}
						if (response.redirectUrl) {
							fillContent(response.redirectUrl);
						}
					},
					error : function(response) {
						let data = response.responseJSON;
						if (data.message) {
							alert(data.message);
						}
						if (data.redirectUrl) {
							fillContent(response.redirectUrl);
						}
						if (data.fieldErrors) {
							for (let fieldName in data.fieldErrors) {
								let fieldMessage = data.fieldErrors[fieldName];
								$('span[data-target=' + fieldName + ']').text(fieldMessage);
							}
						}
					}
				}
				$.ajax(settings);
			})

이렇게 json으로 받은 데이터를 가지고 리다이렉트를 하거나 메시지를 출력하도록 구현하였다. 또한 fieldErrors가 있다면 각 이름의 위치에 맞게 오류 메시지를 띄워주도록 구현하였다. 여기서 주의사항은 성공시에 success에 들어오는 response는 바로 message에 접근이 가능하지만 에러시에는 처리내용이 많아서 responseJSON에서 꺼내서 사용해야 한다는 차이점이 있다.

그의 한마디

고려사항

이벤트 위임을 통해서 모든 js이벤트를 메인 페이지에 작성하고 있는데 이러한 공통되는 CRUD에 처리를 뭔가 모듈화해서 사용하는 것이 맞을 것 같다...

0개의 댓글