IT 강의 정리/윤재성의 스프링 MVC5

[섹션3][Spring MVC의 유효성 검사] 27~33강

Nellie Kim 2022. 10. 25. 20:07
728x90

27. Properties

어플리케이션을 개발할 때 프로그램 실행 중 절대 변하지 않는 값들이 있을 수 있다. 매우 중요한 개념이다.

예를들어, 데이터베이스 접속정보나 업로드폴더경로 등등.. 이러한 값들을 여러군데에서 중복 사용한다면 수정할 때도 여러 코드를 수정해야 하는 번거로움이 있다. 이런 번거로움을 덜기 위해 Properties라는 개념이 있다.

변하지 않는 값들을 properties파일에 작성하고 이를 가져다 사용할 수 있다. 

 

1. 먼저, 아래처럼 data1.properties 파일을 만들어준다.

properties파일을 작성해보자.

그런데 이때 Properties파일에 한글을 작성하면 아래와같이 유니코드문자형태로 변환이 된다. 이러면 유지보수에 어렵다.

Property Editor설치로 해결이 가능하다.

Help - install New Software - Add..- Name은 임의로지정 -  Location:http://propedit.sourceforge.jp/eclipse/updates

프로퍼티파일에 문자가 아래와 같이 잘 입력된다.

2. Controller클래스를 만들고 @PropertySource안에 프로퍼티파일경로 설정, @Value로 값 주입받아 필드로 세팅하기

다수의 프로퍼티파일이 있을 때는 @PropertySources 를 붙여 지정해준다.  정상적으로 잘 주입 받아 출력되었다.

위와 같은 방법 이외에도 아래와 같은 방법으로 프로퍼티파일을 지정할 수 있다.

 

요약 
프로그램 실행 중 절대 변하지 않는 값은 properties 파일을 만들고,

Controller클래스에 @PropertySource안에 프로퍼티파일경로 설정, @Value로 값 주입받아 필드로 세팅하기

 

28. Message

위에서 Properties를 활용하면 다양한 값들을 미리 정의해놓고 이를 가져다 사용할 수 있었다.

그런데 Properites에 작성한 값을 JSP에서 사용하려면, 몇가지 설정이 필요하다.

프로퍼티파일을 Message로 등록해줘야 한다. 그렇게되면 프로퍼티파일을 자바, JSP등 여러곳에서 사용이 가능해진다.

다국어처리도 가능해진다.

MessageSource객체를 이용해 properties파일을 등록해주면 Message로 등록할 수 있다.

여기서는 일정시간마다 한번씩 갱신되는 ReloadableResourceBundleMessageSource를 사용한다.

원래 프로퍼티파일은 서버실행중에 절대 변경할 수 없는 부분이지만, 이 리로더블리소스번들메시지소스를 이용해서 프로퍼티파일을 메시지로 등록해주면 서버를 중지하지 않고 프로퍼티파일 수정하면 바로 반영되어 사용할 수 있게 된다.

Java와 xml에서 설정하는 방법이 다르니 각각 설정해보자.

설정하기

1. Java에서 설정

1) 먼저, 원하는 property파일을 만들고, SevletAppContext클래스에서 아래와 같이 만든파일을 Message로 등록한다. 

주의할 점은 파일의 확장자는 생략하고 입력(data1)해줘야 한다.

2. Xml파일에서 설정

xml에서는 bean설정 뿐만아니라 MessageSource를 사용하기 위해 Accessor라는것도 등록을 해줘야 한다.

Message로 등록된 데이터를 Xml에서 사용하는 방법은 Java와 동일하다.

 

사용하기

컨트롤러에서 @Autowired로 MessageSource를 주입받아서 사용하자.

 

1. 첫번째 매개변수

콘솔에 잘 출력이 되었다.

 JSP파일에도 사용을 해보자.

그냥은 사용하지 못하고 Spring MVC에서 제공하고 있는 message 커스텀태그<spring:message>를 활용해 줘야 한다.

JSP도 잘 출력이 되었다.

 

2. 두번째 매개변수

만약, 문자의 일부분만 계속 변경을 해야하는 경우

아래와 같이 작성 후, 콘솔에 찍어보자.

JSP로 출력을 해보자. 각 자리의 값을 request에 담아서 출력해야한다. Model을 주입받고 jsp에 argument추가하기.

 

3. 세번째 매개변수

이번에는 세번째 매개변수인 Locale을 지정해보자. Locale객체를 주입받아야 한다.

단순히 Locale객체만 주입받고 출력해보면, 콘솔창에 ko라고 찍힌다.

크롬 - 설정 - 언어 - 영어 - 이 언어로 Chrome표시 - 다시시작 - 새로고침 눌러보면 콘솔창에 en_US라고 찍힌다.

즉, 브라우저에 설정되어져있는 언어 값을 가지고 와서 그 값을 지정해 다국어 처리를 한 것이다.

이런식으로 data1_en.properties, data1_ko.properties 만들어놓고, 브라우저의 언어값이 변경될 때마다 콘솔에 출력하는 값이 달라지게 만들 수 있다.  

JSP에는 따로 Locale을 설정하지 않아도 된다. 

요약
Properites파일을 Message로 등록하게 되면 JSP에서도 사용할 수 있으며 다국어처리도 가능해진다.

1) property파일생성 & SevletAppContext클래스에 Message로 등록
2) 컨트롤러에서 @Autowired로 MessageSource를 주입받기 
3) JSP파일에서사용은 message 커스텀태그<spring:message> 사용
(두번째 매개변수는 Model을 주입받고 jsp에 argument추가하기 / 세번째 매개변수는 Locale객체를 주입받기)

29. 유효성 검사

웹 애플리케이션에서 사용자 입력에 대해 유효성을 검사하는 경우가 있다.

JavaScript로 처리할 수도 있지만 Spring MVC를 이용하여 처리할 수도 있다. 

자바스크립트에서 처리를 한다는 말은 브라우저에서 서버로 요청을 보내기 전에 확인하는 것이고,

Spring MVC에서 처리를 한다는 말은 서버에서 일단 요청을 받아 확인하고 저장을 할지말지 결정을 한다는 것이다.

 

JSR-303 

Spring MVC는 JSR-303, JSR-380 규격의 유효성 검사 라이브러리를 사용할 수 있다.

Bean에 데이터가 입력될 때 어떤 검사를 할 것인지 어노테이션으로 지정하고,

지정된 어노테이션의 조건에 맞지 않으면 개발자에게 입력값에 오류가 있다는 정보를 전달한다.

 

1) pom.xml에 두가지 라이브러리 validation-apihibernate-validator 추가하기

JSR-303은 실제 유효성검사를 할 클래스가 존재해야 하는데 여기서는 hibernate(검사도구)라는 라이브러리를 사용하자.

아래와 같이 작성하고 출력해보자.

아래와 같이 콘솔 및 브라우저에 잘 출력된다.

2) 여기에 유효성 검사를 넣어보자.

2-1) DataBean 클래스에 어노테이션을 설정하기.

JSR-303과 Hibernate에서는 다양한 어노테이션을 제공한다. DataBean1에서 @Size, @Max 어노테이션 사용하여

data1에는 최소값2~ 최대값10 까지의 값, data2는 최대100의 값이 들어오게 설정하자. 

 

2-2) 컨트롤러에서 매개변수에 @Valid설정, BindingResult객체 주입받기

컨트롤러의 메소드에 주입받는 Bean에 @Valid를 설정하면 유효성검사를 실시한다.

유효성 검사 결과를 사용하고자 한다면 BindingResult객체를 주입받아야 한다.

BindingResult객체는 errors라는 이름으로 request영역에 저장된다. 이를 이용해 메시지를 출력할 수 있다.

이 객체에는 유효성 검사를 실행한 결과 정보가 담겨있다. 이를통해 컨트롤러에서 사용자가 입력한 값에 문제가 있는지 파악이 가능하다.

실행하고 브라우저에서 범위에 맞는 값을 넣고 확인버튼을 누르면 콘솔창에 0 errors라고 뜬다.

범위에 벗어나는 값을 입력하고 확인을 누르면, 브라우저에는 나타나지만 콘솔창에 2 errors가 뜨고 에러문구들이 뜬다.

3) if문 사용해서 위배된 부분에 에러메세지 출력하기

먼저, 그냥 getCodes() 로 모든 코드를 배열로 뽑아서 출력해보자. 역시나 브라우저에서 위반을 해보면,

아래와 같이 콘솔창에 4줄이 나오는데, 그중에 1번째 줄인 codes[0]을 이용해서 다양한 처리를 할 수 있다.

이어서 컨트롤러에 아래와 같이 if문을 입력해주면, 해당하는 codes[0]을 찾아 콘솔에 알맞은 에러메시지를 출력해준다.

그런데 유효성 검사를 위반했을 때, 다시 입력창으로 돌아와야 하니까, if문 마지막에 input_data를 리턴해줘야 한다. 

 

이번에는 콘솔이 아닌 JSP에서 기본 에러메시지를 나타내보자.

input_data.jsp에 아래 커스텀태그 두줄을 추가해주고,

유효성검사코드 <spring:hasBindErrors>를 아래와 같이 넣어준다. 브라우저에 잘 출력된다.

 

요약 
JSR-303 라이브러리를 활용하면 사용자 입력 데이터에 대한 유효성 검사를 할 수 있다.
1) pom.xml에 라이브러리 validation-api, hibernate-validator 추가 
2) DataBean 클래스에 어노테이션(@Size, @Max 등)을 설정 
3) 컨트롤러에서 매개변수에 @Valid설정, BindingResult객체 주입 
4) input_data.jsp에 커스텀태그추가 & 유효성검사코드 <spring:hasBindErrors>작성

30. 에러메시지 커스터마이징

유효성 검사에서 오류가 있다고 판단되는 항목에 대해서 JSP에서 기본 메시지를 출력했다.

우리가 출력한 메시지는 JSR-303에서 정의한 메시지가 그대로 나오는 것이며 우리가 설정한 문자열은 아니다.

JSR-303과 Hibernate에서 제공하는 어노테이션중 일부는 새로운 메시지를 세팅할 수 있지만 일부는 세팅하지 못한다.

 

유효성 검사를 통과하지 못하면 JSP에 오류 관련된 정보가 전달된다.

이 때 codes[0]으로 값을 가져오면 다음 양식으로 문자열을 가져올 수 있다. (에러종류.빈이름.프로퍼티이름)

우리가 Properties파일에 위와 같은 양식의 이름으로 메시지를 등록해주면 Properties파일에 작성한 문자열을 가져와 출력할 수 있고 다국어 처리까지 가능해진다.

에러메시지 커스터마이징 해보자.

 

1) 에러메시지를 프로퍼티파일에 등록 & ServletAppContext파일에 메시지로 등록하기

2) input_data.jsp에 가서 메시지 추출하기

<spring:message> 태그로 추출해보자. 아래 결과가 브라우저로 출력된다.

그런데, data2에 21억 이상의 숫자를 넣게되면 500 에러가 뜨는데, 이런 상황의 에러메시지를 정의하지 않았기 때문이다.

이럴때는 간단히 해결가능하다. 에러메시지를 복사해서 프로퍼티 파일에 에러메시지를 지정해주면 된다.

선생님의 경우 프로퍼티값이 int으로 지정되어있으면 이런 문제가 발생할 수 있어서 String으로 많이 사용한다고한다. 

그렇게 되면 변수가 String이기 때문에 정수로 변환하지 않고 문자열 자체로 집어넣게 된다. 그대로 유효성검사를 한다.

3) Form데이터 유지하기

유효성 검증에 통과하지 못해 다시 입력화면으로 돌아왔을 때 기존에 입력했던 내용을 유지해야 할 경우가 있다.

이 때, 입력화면으로 전달된 Bean객체에서 input태그에 값을 주입하면 된다. 전에 배운 Form커스텀태그 활용.

이 때, 검증실패 문자열도 손쉽게 세팅이 가능하다.<form:errors>사용

아래의 형태가 최종 유효성 검사 형태이다.

Form데이터 설정까지 완료하면, 유효성에 위반해도 브라우저에서 데이터가 지워지지 않으며 오류메시지까지 출력된다.

요약 )
Properties파일을 활용하면 에러메시지를 설정할 수 있다.
1) 에러메시지를 프로퍼티파일에 등록 & ServletAppContext파일에 메시지로 등록
2) input_data.jsp에서 <spring:message> 태그로 에러메시지추출
3) input_data.jsp에서<form:errors> 사용해서 Form데이터 유지하기 

31. JSR-303

JSR-303 어노테이션은 빈 객체에 주입되는 값의 유효성 검사를 하기 위해 제공되는 어노테이션이다.

여기에서는 자주 사용하는 것만 골라서 보자. 아래 사이트에서는 어노테이션들이 소개가 되어있다.

https://beanvalidation.org/1.0/spec/

 

에러메시지 프로퍼티파일 생성 - ServletAppContext에서 메시지등록 후 사용

- @AssertTrue : true가 아닌 값이 들어오면 오류
- @AssertFalse : false가 아닌 값이 들어오면 오류
- @Max(값) : 값보다 큰 값이 들어오면 오류
- @Min(값) : 값보다 작은 값이 들어오면 오류
- @DecimalMax(value=값, inclusive=true/false) : 값보다 작거나 같은 값이 들어와야 한다. Inclusive가 false면 값은 포함하지 않기 때문에 작은 값이 들어와야 한다. 생략하면 true
- @DecimalMin(value=값, inclusive=true/false) : 값보다 크거나 같은 값이 들어와야 한다. Inclusive가 false면 값은 포함하지 않기 때문에 큰 값이 들어와야 한다. 생략하면 true
- @Null : 값이 들어오면 오류가 발생.
- @NotNull : 값이 들어오지 않으면 오류가 발생.
- @Digits(integer=자릿수,fraction=자릿수) : 지정된 자릿수의 숫자가 아닐 경우 오류가 발생. Integer – 정수 자릿수, fraction – 실수 자릿수
- @Size(min=글자수,max=글자수) : 지정된 글자수 보다 짧거나 길면 오류가 발생
- @Pattern(regexp=정규식) : 주어진 정규식에 위배되면 오류 발생. 모든 프로그래밍언어가 동일. 구글링 할것

@AssertTrue

jsp → DataBean1 → error_message 순으로 작성하기.

에러메시지는 어노테이션이름.클래스이름.변수이름 이기 때문에 제일 마지막에 작성. 

@Pattern(regexp=정규식)

[a-zA-Z] : 소문자 a~z , 대문자 A~Z 로만 구성이 되어야 한다는 의미다.

32. JSR-380

JSR-380 어노테이션은 JSR-303과 원리는 같고 유효성 검사의 편의성을 더하기 위해 추가로 제공되는 부분이다.

https://beanvalidation.org/2.0/spec/

마찬가지로 에러메시지 프로퍼티파일 생성 - ServletAppContext에서 메시지등록 후 사용. 사용법은 동일하다.

- @NotEmpty : 주입된 값의 길이가 0이면 오류 발생. 공백도 글자로 인식합니다.
- @NotBlank : 주입된 값이 공백을 제거하고 길이가 0이면 오류 발생.
- @Positive : 양수가 아니라면 오류 발생
- @PositiveOrZero : 0 또는 양수가 아니라면 오류 발생
- @Negative : 음수가 아니라면 오류 발생.
- @NegativeOrZero : 0 또는 음수가 아니라면 오류 발생.
- @Email : 이메일 형식이 아니라면 오류 발생. 중간에 @가 있는지 정도만 확인한다.

 

33. Validator 커스터마이징

JSR-303, JSR-380 스펙을 이용한 유효성 검사 방법을 학습하였다.

유효성 검사를 한다는 것은 변수의 값을 꺼내서 설정한 조건에 맞는지 맞지않는지 확인하는 코드가 동작을 해야한다.

그런 코드들이 구현되어있는 클래스를 Validator라고 한다.

지금까지는 유효성 검사를 하기 위해 Hibernate를 사용했다. 이번에는 Validator를 직접 만들어 보도록 하자.

JSR-303, JSR-380 스펙으로 유효성 검사를 하는건 부족하다.

예를들어, 우리나라같은 경우 입력한 문자열이 한국어로만 구성되어져있는지 검사한다던지 등등..

대부분은 값이 조건에 맞는지 확인하는 것은 정규식으로 검사가 가능하다.

그런데, 비밀번호와 비밀번호확인을 위해 2번씩 입력하고 두 데이터가 일치하는지 확인하는 것 등은 어노테이션이나 정규식으로 해결하지 못한다. 그래서 Validator를 만들어서 사용하게 된다.

JSR-303, JSR-380 스펙으로 유효성 검사를 한후 추가적으로 다른 유효성 검사를 하고자 할 때 사용합니다.

 

1) 먼저 Validator 인터페이스를 구현하여 2개의 추상 메소드를 구현하기

supports : 유효성 검사할 데이터를 가지고 있는 객체가 유효성 검사가 가능한지 확인한다. @Valid가 붙어있는가?

validate : 실제로 유효성 검사를 하는 메서드. 

 

2) Validator를 컨트롤러에서 등록하기

사용할 Validator하나면 setValidator, 한 개 이상이면 addValidators 메서드를 사용한다.

보통은 객체 하나당 Validator하나 만들어서 Validator를 여러개 만들어서 쓴다.

클래스타입에 따라서 각각 Validator를 만들어주면, 클래스타입에 맞춰서 유효성검사를 따로따로 할 수 있다.

 3) Validator클래스에 유효성 검사 만들기.

3-1) ValidateUtils 작성하기

지정된 값에 대해 유효성 검사를 하는 메서드

rejectIfEmpty(error객체, “프로퍼티이름“, “코드이름“) : 값이 비어 있는지 확인한다. 공백은 글자로 취급.

rejectIfEmptyOrWhitespace(error객체, “프로퍼티이름“, “코드이름“) : 값이 비어 있거나 공백이 있는지 확인한다.

입력값에 문제가 있다면 error객체에 오류정보를 저장한다오류 메시지는 코드이름.bean객체이름.프로퍼티이름

3-2) rejectValue 작성하기

유효성 검사 조건을 직접 만들어 검사하는 메서드

If으로 유효성 검사를 해주고 위배시 rejectValue를 통해 오류 정보를 지정한다.

rejectValue( “프로퍼티이름“, “코드이름“) :

입력값에 문제가 있다면 error 객체에 오류정보를 저장한다. 오류 메시지는 코드이름.bean객체이름.프로퍼티이름

 

요약
1) Validator 인터페이스를 구현하여 2개의 추상 메소드(supports,validate)를 구현하기
2) Validator를 컨트롤러에서 등록하기 (하나면 setValidator, 한 개 이상이면 addValidators 메서드를 사용)
3) Validator클래스에 유효성 검사 만들기 (ValidateUtils / rejectValue 작성)

 

출처 : [인프런] 윤재성의 만들면서 배우는 Spring MVC 5