반응형 Framework & Library/Spring Boot164 [Spring Boot] : FieldError과 ObjectError에 대해서 FieldError과 ObjectError에 대해서 if (!StringUtils.hasText(item.getItemName())) { //넘어온 글자가 없으면 bindingResult.addError(new FieldError("item", "itemName", item.getItemName(), false, null, null, "상품 이름은 필수입니다.")); } 전과 같은데 추가된 부분이 있다. FieldError 는 두 가지 생성자를 제공하는데 이번에는 다른 생성자를 사용해 보았다. Ctrl + p를 누르면 어떤 파라미터 담을 수 있는지 볼 수 있는데 아래와 같다. objectName : 오류가 발생한 객체 이름 field : 오류 필드 rejectedValue : 사용자가 입력한 값(거절된 .. 2022. 2. 10. [Spring Boot] : BindingResult 사용(2) BindingResult 사용(2) BindingResult가 있으면 @ModelAttribute에 데이터 바인딩 시 오류가 발생해도 컨트롤러가 호출된다. 이게 예를 들면 쉽게 이해가 가능하다. 예시로 만약 한 값을 받아오는데 int로 설정을 해뒀다. 근데 문자가 입력되었을 때 BingingResult를 사용하면 페이지 로딩이 되긴 한다. 하지만 BindingResult를 사용하지 않고 int로 받는 값에 문자를 넣는다면 페이지 자체가 로딩되지 않고 오류 페이지가 뜨게된다. 즉, BindingResult가 없으면 400오류 발생과 동시에 컨트롤러가 호출되지 않고 오류 페이지로 이동되고 BindingResult가 있다면 오류 정보(FieldError)를 BindingResult에 담아서 컨트롤러를 정상 호.. 2022. 2. 10. [Spring Boot] : BindingResult 사용(1) BindingResult 사용(1) BindingResult 를 사용해서 조금 더 간단하게 검증 에러를 체크할 수 있다. public String addItemV1(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) 컨트롤러에서 선언해서 사용하는데 중요한 점은 @ModelAttribute 뒤에 BindingResult가 와야 한다는 점이다. 왜냐하면 BindingResult는 Model 객체, 위에서는 Item에 대한 값을 가지고 있기 때문에 순서가 매우 중요하다. Map errors = new HashMap(); //검증 로직 if (!StringUtils.has.. 2022. 2. 10. [Spring Boot] : 타임리프를 통한 검증 코드 추가하기 타임리프를 통한 검증 코드 추가하기 상품 등록에 검증 코드를 추가해주었다. 검증이 처음에는 뭔가 했는데 그냥 쉽게 입력 누락이나 정해진 범위 초과 등 정석에 맞지 않는 부분이 틀렸다고 알려주는 코드를 추가해주는 것이였다. 이것 역시 공모전을 진행하면서 고생했던 부분이었는데 이렇게 쉽게 할 수 있는 것을 보고 많이 배워간다. 예시 코드는 너무 길어서 일부분만 뺴왔다. //검증 오류 결과를 보관 Map errors = new HashMap(); 먼저 컨트롤러에 검증 로직을 추가하기 위해 검증 오류 결과를 보관할 errors를 만들어주었다. if (!StringUtils.hasText(item.getItemName())) { //넘어온 글자가 없으면 errors.put("itemName", "상품 이름은 필수.. 2022. 2. 10. [Spring Boot] : 타임리프 Message 국제화 타임리프 메시지 국제화 이번에는 국제화를 적용해 보았다. label.item=Item label.item.id=Item ID label.item.itemName=Item Name label.item.price=price label.item.quantity=quantity page.items=Item List page.item=Item Detail page.addItem=Item Add page.updateItem=Item Update button.save=Save button.cancel=Cancel messages_en.properties 폴더에 위와 같이 영어로 된 이름을 설정해 주었다. 상품 등록 그리고 위 코드 처럼 전에 설정한 메시지 표현식을 사용해 자동으로 대체가 된다. 이러면 국제화는 간단하.. 2022. 2. 9. [Spring Boot] : 타임리프 웹 애플리케이션 Message에 적용하기 웹 애플리케이션 메시지에 적용하기 label.item.quantity=수량 page.items=상품 목록 button.cancel=취소 먼저 messages.properties에 위와 같이 적어줬다. 위 코드로 다른 제목들을 대체하여 만약 변경 사항이 생길 때 여러 페이지를 왔다갔다 하면서 고치지 않고 messages.properties 파일에서 해당 내용만 변경해 주면 된다. 예를 들어 설명하자면 저장을 저장하기로 바꾸길 원한다면 다른 페이지에서 일일이 다 바꿔 줄 필요없이 messages에서 저장부분을 저장하기로 수정만 해주면 되는 것이다. 타임리프 메시지를 적용하기 위해서는 타임리프의 메시지 표현식을 사용해야 하는데 메시지 표현식은 #{,,,} 이런 형식으로 되어 있다. 상품 등록 예를 들면 상품 .. 2022. 2. 9. [Spring Boot] : 타임리프 MessageSource 사용하기 스프링 메시지 소스 사용 MessageSource 인터페이스 코드를 열어보면 일부 파라미터로 메시지를 읽어오는 기능을 제공하는 것을 확인할 수 있다. @Autowired MessageSource ms; ms.getMessage()는 code, args, locale 값을 받는다. @Test void helloMessage() { String result = ms.getMessage("hello", null, null); assertThat(result).isEqualTo("안녕"); } 아무것도 지정하지 않았을 경우 디폴트 값으로 설정되어 있는 한글로 들어가게 된다. 때문에 비교했을 때 안녕으로 표시되므로 테스트 통과가 된다. 메시지가 없는 경우에는 NoSuchMessageException이 발생하게 된.. 2022. 2. 9. [Spring Boot] : 타임리프 MessageSource 설정 메시지 관리 기능을 사용하기 위해 MessageSource를 스프링 빈으로 등록해야 하는데 스프링 부트에서는 간단하게 지원을 해준다. spring.messages.basename=messages properties에 이렇게 메시지 소스를 적어주기만 하면 된다. hello=안녕 hello.name=안녕 {0} messages.properties에는 이렇게 한글로 적어주고 hello=hello hello.name=hello {0} messages_en.properties에는 이렇게 영어로 적어주었다. 이러면 디폴트 값이 한국으로 잡히게 되고 en으로 들어오게 되면 hello가 나오고 그 외 모든 언어는 한글로 안녕이 표시되게 된다. 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고하여 공부하였습니다. 2022. 2. 9. [Spring Boot] : 타임리프 Message(메시지), 국제화 메시지, 국제화 소개 만약 상품명이라는 단어를 모두 상품이름으로 고쳐달라는 기획자가 나타나면 전부 다 수정해 주어야 한다. 하지만 여러 화면에 있는 label을 모두 찾아가면서 변경해야 하는데 너무 비효율적이게 된다. 때문에 이런 다양한 메시지를 한 곳에서 관리하도록 하는 기능을 메시지 기능이라고 한다. 예를 messages.properteis라는 메시지 관리용 파일을 만들면 HTML은 데이터를 key 값으로 불러 사용한다. 여기에서 더 나아가 별도로 관리하는 김에 파일을 한개 더 만들어 다른 나라 언어로 사용할 수 있게 해준다. messages_en.propertis messages_ko.propertis 이렇게 두 개의 파일을 만들면 한글과 영어가 지원되게 된다. 이떄, 영어를 사용하는 사람은 _en.. 2022. 2. 9. [Spring Boot] : 타임리프 셀렉트 박스 타임리프 셀렉트 박스 셀렉트 박스는 여러 선택지 중 하나를 선택할 떄 사용한다. 이번에도 역시 자바 객체를 사용하는 방법으로 진행했다. @ModelAttribute("deliveryCodes") public List deliveryCodes() { List deliveryCodes = new ArrayList(); deliveryCodes.add(new DeliveryCode("FAST", "빠른 배송")); deliveryCodes.add(new DeliveryCode("NORMAL", "일반 배송")); deliveryCodes.add(new DeliveryCode("SLOW", "느린 배송")); return deliveryCodes; } 여기서 강사님이 팁을 주셨는데 deliveryCodes() .. 2022. 2. 8. [Spring Boot] : 타임리프 라디오 박스 타임리프 라디오 박스 타임리프를 활용해서 라디오 박스를 만들어 본다. 라디오 박스는 체크 박스와 다르게 여러개 중 하나만 선택할 수 있다. 이번에는 ENUM을 활용해서 개발을 진행했다. @ModelAttribute("itemTypes") public ItemType[] itemTypes() { return ItemType.values(); } @ModelAttribute로 만들어 주었다. 등록, 조회, 수정 모두 다 사용하므로 이렇게 만드는 게 중복을 줄이는 방법이다. return 형식이 조금 다른데 저렇게 사용하면 ENUM의 모든 정보를 배열로 반환하게 된다. 핵심 코드이다. 체크 박스와 비슷하지만 차이점으로는 항상 하나만 선택이 가능하기 때문에 따로 히든 필드를 사용하지 않아도 된다. 타임리프에서 E.. 2022. 2. 8. [Spring Boot] : 타임리프 체크 박스 여러개 만들고 체크하기 체크 박스를 여러개 만들고 복수 체크가 가능하도록 만들 수 있다. 그 전에 @ModelAttribute 어노테이션도 사용해 봤는데 이 어노테이션은 여러 화면에서 체크 리스트 내용을 중복으로 보여줘야 할 때 각각 Mapping부분에 중복해서 적어주지 않고 별도의 메서드를 만들어 사용할 수 있다. 그렇게 되면 컨트롤러를 요청할 때 @ModelAttribute에서 반환한 값이 자동으로 model에 담기게 된다. @ModelAttribute("regions") public Map regions() { Map regions = new LinkedHashMap(); regions.put("SEOUL", "서울"); regions.put("BUSAN", "부산"); regions.put("JEJU", "제주"); r.. 2022. 2. 8. [Spring Boot] : 타임리프 체크 박스 단일(2) 타임리프 체크박스 단일(2) 전에 했었던 히든 필드를 추가하여 true, false를 반환 받는 방법 말고 타임리프가 제공하는 폼 기능을 사용해 해당 부분을 자동화해서 사용할 수 있다. 이랬던 기존 코드를 이렇게 바꿔주기만 하면 된다. 타임리프를 사용하면 hidden 필드와 관련된 부분이 해결이 된다. 이 상태로 확인을 해보면 정상적으로 체크는 true, 체크가 되어있지 않으면 false가 된다. 두번째 라인 부분이 타임리프의 체크 확인 코드이다. 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고하여 공부하였습니다. 2022. 2. 8. [Spring Boot] : 타임리프 체크 박스 단일(1) 타임리프 체크 박스 단일(1) HTML에서 이런 식으로 보통 체크 박스를 사용한다. 체크 박스를 체크하게 되면 open=on으로 들어오고 스프링에서 on을 true타입으로 변환해준다. 이때 스프링 타입 컨버터가 작동하여 이렇게 되는 것인데 이것은 다른 강의에서 다룬다고 한다. 문제는 체크 박스를 체크하지 않았을 때 발생한다. 체크 박스를 체크하지 않고 폼을 전송하게 되면 open이라는 필드 자체가 서버로 전송되지 않는다. 즉, 아무런 값이 들어오지 않아 이게 어떻게 된 것인지 알 수가 없는 것이다. 값 또한 찍어보면 null 값이 나타나는데 이 경우 문제가 생길 확률이 있다. 이걸 해결하는 방법도 강의에서 알려주었다. 체크 해제를 인식하기 위해 히든 필드를 넣어주는 것이다. 이렇게 되면 체크 박스를 체크.. 2022. 2. 8. [Spring Boot] : 타임리프 입력 폼 처리하기 th:object와 th:field 사용 타임리프 입력 폼 처리 폼 코드를 타임리프의 추가 기능을 통해 효율적으로 개선할 수 있다. 강의에서 몇 가지 주요 코드를 사용했는데 아래와 같다. th:object 커맨드 객체를 지정한다. *{...}} 선택 변수식으로 th:object에서 선택한 객체에 접근한다. 아래 예시에서 보면 이해가 편하다. th:field HTML 태그의 id, name, value 속성을 자동 처리해준다. model.addAttribute("item", new Item()); 먼저 컨트롤러에서 객체를 넘겨준다. 폼 태그에 th:object 속성을 사용해 model에서 전달한 객체의 이름을 넣어주고 사용하게 된다. 이렇게 줄여 쓸 수 있다. id를 지우면 상관이 없는 빨간 줄이 뜨기 때문에 강사님이 남겨둔 것 같다. 원래는”$.. 2022. 2. 8. [Spring Boot] : 타임리프 스프링 통합 메뉴얼 및 스프링에서 사용하기 타임리프 스프링 통합 타임리프의 2가지 메뉴얼이다. 📝 ← 기본 메뉴얼 📝 ← 스프링 통합 메뉴얼 타임리프는 스프링 없이도 동작하고 스프링과 통합을 위해 편의 기능을 더 제공하기도 한다. 강의 자료에 따르면 스프링 통합으로 추가되는 기능들은 SpringEL 문법, 스프링 빈 호출 지원, 폼 관리를 위한 추가 속성, 폼 컴포넌트 기능 등 여러 가지를 지원한다. 📝, 📝 ← 타임리프 템플릿 엔진을 스프링 빈에 등록하고, 타임리프용 뷰 리졸버를 스프링 빈으로 등록하는 방법이다. 다른 방법으로는 아래와 같다. implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' build.gradle에 위 코드를 넣으면 스프링 부트가 자동으로 설정해 준.. 2022. 2. 8. [Spring Boot] : 타임리프 템플릿 레이아웃(2) 타임리프 - 템플릿 레이아웃(2) 앞에서 사용한 레이아웃을 메인 페이지 컨텐츠 메인 페이지 포함 내용 title과 section을 layout에 담아 layoutFile.htm로 전달해 주면 위에 짠 레이아웃 코드에 적용되어 대체된 상태로 출력되게 된다. 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고하여 공부하였습니다. 2022. 2. 7. [Spring Boot] : 타임리프 템플릿 레이아웃(1) 타임리프 - 템플릿 레이아웃(1) 이번에는 코드 조각을 레이아웃에 넘겨 사용하는 방법에 대해 공부한다. 강의 자료에서 예를 잘 들어 주었는데 layoutMain.html이다. 여기에서 넘겨주는 것이다. template/layout/base :: common_header(~{::title},~{::link}) 이 라인이 핵심인데 common_header를 불러주면서 옆에 title와 link를 담아 전달한다. 그러면 base.html에서 받고 렌더링하고 추가되는 부분도 맞추어 값을 전달하게 된다. 이렇게 되면 메인 타이틀이 전달한 부분으로 교체되고 공통 부분은 유지되며 추가 부분에 전달한 들이 포함되는 것을 확인할 수 있다. 즉, 레이아웃 개념을 두고 그 레이아웃에 필요한 코드 조각을 전달해 완성한다고 보.. 2022. 2. 7. [Spring Boot] : 타임리프 템플릿 조각 사용 타임리프 - 템플릿 조각 웹 페이지 개발 시 여러 페이지에서 공통으로 겹치는 부분이 있다. 예를 들면 상단, 하단 등 이런 부분을 코드 복사로 사용하면 오류가 날 수도 있고 비효율적인데 이런 것을 해결하기 위해 타임리프에서 템플릿 조각과 레이아웃 기능을 지원한다. 그 중 템플릿 조각을 먼저 공부해 본다. 먼저 footer.html에 위 코드를 작성해 주었다. th:fragment 를 통해 사용할 수 있다. 이름을 먼저 copy로 정해주었다. 부분 포함 insert 부분 포함 replace 부분 포함 단순 표현식 fragmentMain.html에는 위 코드를 작성해 주었다. ~{template/fragment/footer :: copy} 이 코드를 보면 template/fragment/footer.html.. 2022. 2. 7. [Spring Boot] : 타임리프 JavaScript inline 사용 타임리프 - JavaScript 인라인 타임리프에서 편리하게 JavaScript를 사용할 수 있는 인라인 기능을 제공한다. 위 코드처럼 사용하면 JS안에서도 each사용도 가능하다. 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고하여 공부하였습니다. 2022. 2. 7. [Spring Boot] : 타임리프 block 사용 타임리프 - block 타임리프는 속성으로 보통 제공되지 태그로 작동하지는 않는데 타임리프에서 제공하는 태그가 있다. 바로 block 태그인데 이 태그는 each를 통해 반복할 때 div 두 개를 반복해야 하는 상황에 사용할 수 있다. 사용자 이름1 사용자 나이1 요약 보면 div 두개가 있지만 each를 div에 주지 않고 th에 주어 반복한다. 결과도 출력해 보면 두 div가 반복되는 것을 확인할 수 있다. block 태그는 렌더링 시 제거가 된다. 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고하여 공부하였습니다. 2022. 2. 7. 이전 1 2 3 4 5 6 7 8 다음 반응형