월 24,200원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
LoginForm클래스가 web영역인 이유가 궁금합니다.
멤버 클래스, 멤버 리포지토리 클래스와 비교하였을 때 멤버 클래스는 도메인 영역에 존재하고 멤버 리포지토리에 의해서 멤버 클래스의 객체가 만들어지는것 같은데로그인기능에서 로그인폼 클래스가 멤버 클래스와 같은 기능인것 같은데 서로 다른 영역에 존재하고 로그인 사용자가 생성될려면 로그인서비스의 loginService.login()기능이 호출되어서 로그인 객체가 생성이 되는것을 알겠는데 멤버클래스와 다르게 web영역에 존재하는 이유가 궁금합니다.
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
검증1 강의 내용 질문
<div> <label for="itemName" th:text="#{label.item.itemName}">상품명</label> <input type="text" id="itemName" th:field="*{itemName}" th:errorclass="field-error" class="form-control" placeholder="이름 을 입력하세요"> <div class="field-error" th:errors="*{itemName}"> 상품명 오류 </div> </div>FieldError()의 생성자에는 message가 항상 들어가있는데, 여기서 저 "상품명 오류"라는 문자는 출력될 일이 있는 건가요? 아니면 단순히 div 태그를 구분하기 위해 적혀있는 건가요?
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
만약에 여러사람과 협업한다고 가정시에
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.저 뿐만이 아닌 다른 여러사람과 협업한다고 가정 시에 각자 자신의 프로젝트 루트가 다를 텐데 application.properties에 선생님과 똑같게 경로를 지정하면 이게 모두에게 적용이 되느건가요?? 아니면 뭔가 다른 방식으로 접근해야 되나요??
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
api 예외처리 시작 프로그램 오류
postman에서 http://localhost:8080/api/members/ex 를 입력하면 인텔리제이 콘솔에 아래와 같은 오류 메세지가 뜹니다. api 예외처리 - 시작 첫번째 예시 프로그램입니다.(소스는 교유자료 그대로 카피했습니다.)부트 3.2.4. 자바 17 입니다.https://drive.google.com/file/d/1dF6tbyoy58KHPVdXYeiMYbGkPqnD9HVy/view?usp=sharing 2024-04-13T11:04:18.249+09:00 ERROR 12968 --- [exception] [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost] : Exception Processing [ErrorPage[exceptionType=java.lang.RuntimeException, location=/error-page/500]]jakarta.servlet.ServletException: Request processing failed: java.lang.NullPointerException: Cannot invoke "java.lang.Exception.getMessage()" because "ex" is null 디버그를 잡아보면 @RequestMapping(value = "/error-page/500", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Map<String, Object>> errorPage500Api(HttpServletRequest request, HttpServletResponse response) { log.info("API errorPage 500"); Map<String, Object> result = new HashMap<>(); Exception ex = (Exception) request.getAttribute(ERROR_EXCEPTION);여기가지 실행하면 ex에 null 이 나옵니다. 이거 때문에 오류가 나는데 이유가 뭘까요? 그래서 status만 찍게 했더니 500 이 아니라 null이 출력되네요?API errorPage 500ERROR_EXCEPTION: ex=ERROR_EXCEPTION_TYPE: nullERROR_MESSAGE: nullERROR_REQUEST_URI: nullERROR_SERVLET_NAME: nullERROR_STATUS_CODE: null
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
레이아웃 파일에 <!DOCTYPE html> 선언이 안 되어 있는 이유
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]1. 타임리프 - 기본 기능.pdf(v20240408)에서45 페이지에 있는 base.html 코드를 보면 <!DOCTYPE html> 이게 선언되어 있지 않은데 레이아웃 파일엔 안 써도 되는 건가요? 혹시 써야 하는데 빠진 거일지도 몰라서 제보합니다.
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
인라인을 사용할 때의 이스케이프 처리와 인라인을 안 쓸 때의 이스케이프 처리 차이
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]@GetMapping("/javascript") public String javascript(Model model) { model.addAttribute("user", new User("user\"A\"", 10)); addUsers(model); return "basic/javascript"; }컨트롤러에선 위 코드에 나온 대로 model.addAttribute("user", new User("user\"A\"", 10));이렇게 한 다음, javascript.html은<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script type="text/javascript"> var username = "[[${user.username}]]"; document.write(username); </script> <script th:inline="javascript" type="text/javascript"> var username = [[${user.username}]]; document.write(username); </script> </body> </html>이렇게 수정했습니다.(자바스크립트를 제대로 배운 게 아니라서 이렇게 코드를 짜도 되는지 모르겠습니다.) 서버를 실행하면인라인 사용 전이나 후나 똑같이user"A"이렇게 보입니다. 페이지 소스 보기를 누르면이렇게 뜹니다. 인라인 사용 전이나 사용 후 모두 이스케이프 처리된 거 아닌가요? 인라인을 사용하지 않아도 이스케이프 처리를 해 주는데, 자바스크립트 인라인을 사용해서 다른 모양(?)으로 이스케이프 처리를 해 주는 이유가 궁금합니다. 인라인을 사용하지 않은 이스케이프 처리는 문제가 생길 수 있나요?(혹시 HTML Entity는 HTML 코드 작성 부분에서만 생겨도 되고, 자바스크립트 코드 안에선 생기면 HTML Entity가 생기면 안 되는 건가요?) 이스케이프를 HTML Entity로 처리하는 것과 자바스크립트 인라인을 통해 이스케이프 처리를 하는 건 어떻게 다른지 궁금합니다.
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
자바스크립트 주석과 HTML 주석의 차이?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!-- 자바스크립트 인라인 사용 전 --> <script> var username = [[${user.username}]]; var age = [[${user.age}]]; //자바스크립트 내추럴 템플릿 var username2 = /*[[${user.username}]]*/ "test username"; //객체 var user = [[${user}]]; </script>이 코드에서 '자바스크립트 내추럴 템플릿' 부분에 있는 주석에 대해 궁금한 점이 있습니다. 서버를 실행한 후 페이지 소스 보기를 누르면주석 사이에 [[${user.username}]]가 아닌 userA가 보입니다. 그런데 이전의 주석 강의에선똑같이 서버 실행 후 페이지 소스 보기를 눌렀는데 ${data} 그대로인 채로 있습니다. 그래서 이번 강의에서도 주석 사이에 [[${user.username}]]로 되어 있을 줄 알았는데 userA로 변환이 되어 있더라고요. 강의에서 말씀해 주셨던 내용들 참고하면 "자바스크립트 코드는 서버에서 동작하지 않고, HTML 코드는 서버에서도 동작하며, 마찬가지로 자바스크립트 주석도 서버에선 동작하지 않고 HTML 주석은 서버에서도 동작한다." 이렇게 생각되긴 하는데 이 내용 때문이 맞는지, 그리고 이 내용에 오류가 없이 정확한지 확신이 안 들어서 질문드립니다.
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
한번만 질문 봐주십쇼..
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.안녕하세요 검증 부분을 수강하고 프로젝트에 적용하는데 잘 모르겠는 부분이 생겨서 질문드립니다@PostMapping("/blog/post") public String addOrUpdate(@ModelAttribute RequestPost requestPost, BindingResult bindingResult, Model model){ requestPostValidation.validate(requestPost,bindingResult); if(bindingResult.hasErrors()){ System.out.println(bindingResult); model.addAttribute("post",requestPost); return "addOrUpdate"; } if(requestPost.getId()==null){ postService.savePost(requestPost.toPost()); return "redirect:/blog"; } else{ postService.updatePost(requestPost); ResponsePost post = new ResponsePost(postService.findById(requestPost.getId())); model.addAttribute("post",post); return "redirect:/blog/post/"+post.getId(); } }이게 컨트롤러부분이고 @Component public class RequestPostValidation implements Validator { @Override public boolean supports(Class<?> clazz) { return RequestPost.class.isAssignableFrom(clazz); } @Override public void validate(Object target, Errors errors) { RequestPost requestPost = (RequestPost)target; if(!StringUtils.hasText(requestPost.getTitle())){ errors.rejectValue("title","noTitle"); } if(!StringUtils.hasText(requestPost.getContent())){ errors.rejectValue("content","noContent"); } } }이게 검증하는 클래스입니다noTitle.requestPost.title=제목은 필수입니다. noContent.requestPost.content=내용은 필수입니다.에러 메시지는 이렇게 만들어 줬구요<form action="/blog/post" method="POST" th:object="${post}"> <input type="text" th:value="${post.id}" name="id" style="visibility: hidden;"> <h3>제목</h3> <input th:if="${post.id==null}" type="text" placeholder="제목 입력하시오" th:value="${post.title}" name="title"> <input th:if="${post.id!=null}" type="text" th:value="${post.title}" name="title"> <div th:errors="*{title}"> 제목 오류 </div> <h3>내용</h3> <textarea th:if="${post.id==null}" placeholder="내용 입력하시오" th:text="${post.content}" name="content"></textarea> <textarea th:if="${post.id!=null}" th:text="${post.content}" name="content"></textarea> <div th:errors="*{content}"> 내용 오류 </div> <br> <div class="center"> <input th:if="${post.id==null}" type="submit" value="등록"> <input th:if="${post.id!=null}" type="submit" value="수정"> <input th:if="${post.id==null}" type="button" th:onclick="|location.href='@{/blog}'|" value="취소"> <input th:if="${post.id!=null}" type="button" th:onclick="|location.href='@{/blog/post/{id}(id=${post.id})}'|" value="취소"> </div> </form> 이게 뷰 부분입니다1.컨트롤러에서 @ModelAttribute RequestPost requestPost 를 통해서 form 정보를 받는데 @ModelAttribute니까 Model에 requestPost 객체가 저장된다고 알고 있습니다 2.그런데 뷰 에서 form이 th:object="${post}"로 되어있어서 model.addAttribute("post",requestPost)로 post이름으로 requestPost 객체를 넣었습니다 3.그럼 제 생각에는 Model에 post이름으로 requestPost 객체가 있으니까 th:object="${post}" 매핑되어서 th:errors="*{title}" 를 통해 title필드가 문제가 있으면 오류메시지가 출력될거라 생각했는데 안됩니다. 4.여러가지를 시도를 해봤는데 model.addAttribute("post",requestPost) 를 하지 않고 @ModelAttribute("post")RequestPost requestPost 를 하고 메시지를 noTitle.post.title=제목은 필수입니다. 로 바꾸니까 그제서야 출력이 되더라고요 5.이게 BindingResult랑 Model에 저장된 객체의 이름이 달라서 이런 일이 발생하는 건가요? 제 생각으로는 model.addAttribute("post",requestPost) 하면 Model에 이름이 post로 저장이 되서 th:object="${post}"랑 매핑은 되는데 th:errors="*{title}"이거는 post 이름으로 BindingResult에서 객체이름을 찾는데 제가 올린코드에서는 requestPost로 저장되어 있어서 못찾는 건가요? 질문을 깔끔하게 하려고 여러번 지웠다 썻다 하는데도 난잡해서 죄송합니다. 제일 궁금한건 컨트롤러에서 @ModelAttribute RequestPost requestPost,BindingResult bindingResult 이렇게 인자를 받고 model.addAttribute("post",requestPost) 해서 뷰로 넘겼을때 th:object="${post}"를 하면 post이름으로 객체를 찾아서 requestPost랑 매핑은 되는데 th:errors="*{title}"를 통해서 오류를 검사할때는 BindingResult에서 post이름으로 객체를 찾아서 오류 출력하는데 현재 BindingResult에는 requestPost로 객체이름이 저장되어 있으니까 출력하지 못하는 걸까요? 한번만 봐주시면 감사하겠습니다..
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
쿠키의 path에 대해 질문드립니다.
package com.myproject.jpaboard.web.controller; import com.myproject.jpaboard.domain.Member; import com.myproject.jpaboard.web.form.LoginForm; import com.myproject.jpaboard.web.repository.MemberRepository; import com.myproject.jpaboard.web.service.LoginService; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; @Controller @RequestMapping("/login") @RequiredArgsConstructor @Slf4j public class LoginController { private final LoginService loginService; private final MemberRepository memberRepository; @GetMapping("/login") public String showLogin(Model model) { model.addAttribute("loginForm", new LoginForm()); return "login"; } @PostMapping("/login") public String processLogin(@Validated @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletResponse response) { if (!loginService.loginCheck(form.getEmail(), form.getPassword(), bindingResult)) { log.info("errors={}", bindingResult); return "login"; } // loginCheck에 통과하면 Member 반환 Member loginMember = loginService.findByLoginEmail(form.getEmail(), bindingResult);// findByEmail했을 떄 Member 하나만 나와야한다. // 로그인 성공 처리 TODO Cookie idCookie = new Cookie("memberId", String.valueOf(loginMember.getId())); response.addCookie(idCookie); System.out.println("login success"); return "redirect:/"; } } 개인적으로 컨트롤러를 만들어서 테스트를 해보고 있는데 쿠키의 path가 루트가 아닌 '/login'으로 등록되어있더라구요. 그래서 url이 루트에 해당하는 HomeController에서 @CookieValue로 위에서 만든 쿠키를 받으려고 해도 받아지질 않습니다. 의도치 않게 쿠키의 path가 생기는 이유에 대해 알고싶습니다.
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
no matching variant 오류가 해결되지 않습니다.
아래 링크에서 지시한데로 https://www.inflearn.com/questions/1232895/no-matching-variant-%EC%98%A4%EB%A5%98 6번까지 다 수행했는데 아래와 같은 메세지가 뜹니다. 지원되지 않는 Gradle JVM.빌드가 현재 Java 17.0.10와(과) Gradle 6.8.2을(를) 사용하도록 구성되었습니다.가능한 솔루션:- Java 15을 Gradle JVM으로 사용: Gradle 설정 열기- Gradle 8.5(으)로 업그레이드하고 다시 동기화- Gradle 7.2(으)로 업그레이드하고 다시 동기화] "Gradle 8.5(으)로 업그레이드하고 다시 동기화하"를 클릭하니까 아래와 같은 메세지가 뜨고, 어노테이션도 인식 못하네요???Cannot use connection to Gradle distribution 'https://services.gradle.org/distributions/gradle-8.5-bin.zip' as it has been stopped.
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
오류메시지 우선순위
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]오류코드가 구체적=>덜구체적 순으로 우선순위를 가진다는 것은 이해가 됐습니다.근데 만약 전체적으로 required(필수값 입니다.)로 메시지를 설정하고 싶고, 상품관련 화면에서만 required.item.itemName(상품 이름은 필수값입니다.)를 설정하고 싶다고 할 때필수값 입니다. 로 나타내고 싶은 화면도 모두 상품 이름은 필수값입니다. 라고 나타날 텐데 이런 경우에는 어떻게 사용하나요?아에 다른 에러코드명으로 생성 후 소스 수정해야하나요?
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
로그인 세션 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 로그인을 하면 세션 생성후 session.setAttribute해서 멤버정보를 넣어둘텐데그러면 타임리프에서 유저의 정보를 모델에서가 아닌 세션에서 꺼내는건 혹시 어떻게 생각하시나요?html두개로 로그인한쪽의 html에서 th:text="${member.name}" 이 아닌th:if="{session.loginMember} != null" th:text="${session.loginMember?.userId}" 이렇게 구현하면은 html 파일 하나로도 구현할수있을거같아 강사님의 생각은 어떠하신지 여쭈어보고싶습니다! 또 한가지는 로그인을 한 상태에서 로그인url (/login)로 이동되는건 컨트롤러에서 막아야할지 혹은 인터셉터로 막아야할지 고민이라 이것에 대해서도 여쭙고싶습니다 ㅜㅜ
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
현재 index.html이 뜨지 않고, 이전에 실행한 index.html화면이 뜹니다.
밸리데이션 프로젝트 index.html 입니다. 이 상태로 실행했는데 화면에는 폼 프로젝트 화면이 뜹니다. (이 프로젝트 실행전에 폼프로젝트를 실행했었습니다.)새로고침을 해도, 다시 시작해도, 새화면에서 띄워도 마찬가지입니다. index.html 파일을 삭제하고 새로 만들면 정상 화면이 뜨는데 이유가 뭘까요? (다른 프로젝트 실행때도 동일한 현상이 계속 나타났었습니다)
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
필드 오류 메세지를 골라 쓸수는 없나요?
메세지를 관리하는 공통 관리팀에서필드에 대한 required 메세지 4가지를 정의해 놨다고 가정할 때required.item.itemName=상품 이름은 필수입니다. required.itemName=이름은 필수입니다. required.java.lang.String = 필수 문자입니다. required = 필수 값 입니다.아래 명령어는bindingResult.rejectValue("itemName","required");required.item.itemName으로 정의된 에러 메세지(상품 이름은 필수입니다.)만 불러 올 수 있는거죠?개발자가 네가지 오류 메세지 중에서 선택해서 사용할 수 있는 방법은 없나요?
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
build.gradle을 변경하면 오류가 납니다. 이유가 뭘까요?
validation 프로젝트 진행 중 build.gradle을 아래와 같이 변경하면 그래들 빌드 오류가 납니다.다른 프로젝트들을 진행할 때는 문제가 없었는데 이유가 뭘까요? A problem occurred configuring root project 'validation'.> Could not resolve all artifacts for configuration ':classpath'. > Could not resolve org.springframework.boot:spring-boot-gradle-plugin:3.2.4. Required by: project : > org.springframework.boot:org.springframework.boot.gradle.plugin:3.2.4 plugins { id 'java' id 'org.springframework.boot' version '3.2.4' id 'io.spring.dependency-management' version '1.1.4' } group = 'test' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() }
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
no matching variant 오류???
인텔리제이를 처음 기동하면 아래 메세지가 뜹니다. 무슨 오류인가요?plugins { id 'java' id 'org.springframework.boot' version '3.2.4' id 'io.spring.dependency-management' version '1.1.4' } group = 'hello' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() }
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
웰컴페이지를 못 찾는 것 같습니다.
최초 실행시에는 index.html 내용이 잘 떴었는데ValidationItemControllerV1 에서 오류를 처리하도록 프로그램을 수정한 후에 실행하니까 안되네요??? index.html 이 존재하고 있는데status 404 오류가 뜹니다.
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
PathVariable 앞에 커스텀 애노테이션을 붙이면 동작이 안 됩니다.
안녕하세요!@PathVariable 앞에 제가 만든 커스텀 애노테이션을 붙인 후 ArgumentResolver가 동작 되길 기대 했으나, supportsParameter나 resolveArgument에 어떠한 log가 찍히지 않는 것을 확인 했습니다.그런데 이유는 모르겠지만 @ModelAttribute 앞에 커스텀 애노테이션을 붙였을 때에는 동작 하더라고요. 왜 PathVariable 앞에 커스텀 애노테이션을 붙였을 경우에는 동작이 안 되는 지 모르겠습니다.구글링이나 GPT를 통해서도 열심히 찾아 봤으나 그 이유를 찾지 못했는데요. 문제점이 무엇인지 알려주시면 감사 드리겠습니다..!// 커스텀 애노테이션 @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface Month { } // 컨트롤러 public Class 클래스 { ...... public 리턴타입 메서드(@Month @PathVariable Integer month) {} } // ArgumentResolver @Slf4j public class MonthArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { log.info("MonthArgumentResolver supportsParameter={}", parameter); return parameter.hasParameterAnnotation(Month.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { HttpServletRequest httpServletRequest = (HttpServletRequest) webRequest.getNativeRequest(); log.info("MonthArgumentResolver resolveArgument={}", httpServletRequest); return 1; // 임시로 1로 반한 함 } } // config @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new MonthArgumentResolver()); } }
- 해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
Thymeleaf 3.1에서의 thymeleaf-extras-java8time 관련 업데이트 사항
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]강의에선 인텔리제이 우측 Gradle의 Dependencies에서 thymeleaf-extras-java8time 라이브러리를 찾을 수 있었는데, 제 인텔리제이에선 찾을 수 없더라고요. 검색해 보니 아래 링크에서https://www.thymeleaf.org/doc/articles/thymeleaf31whatsnew.html 1.4. Core support for the java.time package 항목에 The thymeleaf-extras-java8time extras module has been integrated into the Thymeleaf core: the #temporals expression utility object is now always available. 이렇게 나와 있습니다.타임리프 3.1부터는 스프링 부트가 자동으로 라이브러리를 추가해 줄 필요도 없이, 바로 사용할 수 있는 거로 변경된 거라고 보면 될까요? +)https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#appendix-b-expression-utility-objects 타임리프 3.1 공식 문서 튜토리얼에 Temporals(java.time) 관련 내용이 추가되었습니다.1. 타임리프 - 기본 기능.pdf(v20240224)에 있는 공식 문서는 3.0이라서 링크 첨부드립니다.
- 미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
ModelAttribute 사용 이유가 헷갈립니다.
@Slf4j @Controller @RequiredArgsConstructor public class LoginController { private final LoginService loginService; @GetMapping("/login") public String loginForm(@ModelAttribute("loginForm") LoginForm form) { return "login/loginForm"; } @PostMapping("/login") public String login(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "login/loginForm"; } Member loginMember = loginService.login(form.getLoginId(), form.getPassword()); if (loginMember == null) { // 정보 불일치 시... // reject : 글로벌 오류 bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다."); return "login/loginForm"; } // 로그인 성공 처리 // TODO return "redirect:/"; // 성공 시 홈으로 리다이렉트 } }안녕하세요 '로그인 기능' 강의를 듣고 궁금한 점이 생겨 질문을 올립니다. @GetMapping("/login") public String loginForm(@ModelAttribute("loginForm") LoginForm form) { return "login/loginForm"; }위 메서드는 "/login"이라는 GET 요청이 오면 loginForm 파일을 실행하게 됩니다. 따라서 단지 화면을 출력하는 역할에 불과한데, 왜 @ModelAttribute("loginForm") LoginForm form을 작성하신건지 이해가 잘 가지 않습니다. @GetMapping("/login") public String loginForm() { return "login/loginForm"; }그냥 위처럼 작성하면 안되는건가요? 만약 PostMapping처럼 데이터를 저장하는 요청이라면, ModelAttribute를 통해 LoginForm의 인스턴스를 저장하는 것이 이해가 가지만,GetMapping에는 왜 작성하신건지 이해가 잘 안갑니다 ㅠㅠ감사합니다.