본문 바로가기
IT/Spring

[Spring] - 스프링부트에서 스프링 밸리데이션 @Valid 어노테이션으로 유효성 검사(Validation) 하는 방법

by 차이나는 개발자 2023. 4. 2.
728x90
반응형

#스프링부트에서 스프링 밸리데이션 @Valid 어노테이션으로 유효성 검사(Validation) 하는 방법

-클라이언트뿐만 아니라 서버에서도 유효성검사가 필요합니다.

-스프링에서는 @Valid 어노테이션을 사용해서 각 필드에 대한 유효성 검사를 할 수 있습니다.

-다양한 어노테이션을 사용하여 유효성 검사를 할 수 있습니다.

 

 

#Spring Validation을 사용하려면 pom.xml에 Maven 의존성을 추가해줘야 합니다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.5.6</version>
</dependency>

 

 

#Controller

-메서드 파라미터 제일 앞에 @Valid 어노테이션을 사용해 줘야지 유효성검사를 할 수 있습니다.

package com.org.test.controller;

import javax.validation.Valid;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.org.test.dto.MemberDto;
import com.org.test.dto.Message;

@RestController
public class MemberController {
	
	@PostMapping("/insert")
	public ResponseEntity<Message> insertMember(@Valid @RequestBody MemberDto memberDto) {
		
		Message message = new Message();
		message.setMessage("성공");
		message.setData(memberDto);
		
		return new ResponseEntity<>(message, HttpStatus.OK);
	}
	
}

 

 

#Message

package com.org.test.dto;

import lombok.Data;

@Data
public class Message {
    private String message;
    private Object data;

    public Message() {
        this.data = null;
        this.message = null;
    }
    
}

 

 

#MemberDto

-주로 사용하는 @Valid 어노테이션 관련 어노테이션 종류입니다.

 * @Null: null만 허용합니다.
 * @NotNull: null을 허용하지 않습니다. "", " "는 허용합니다.
 * @NotEmpty: null, ""을 허용하지 않습니다. " "는 허용합니다.
 * @NotBlank: null, "", " " 모두 허용하지 않습니다.
 * @Max(value = ): value 이하의 값을 받을 때 사용됩니다.
 * @Min(value = ): value 이상의 값을 받을 때 사용됩니다.
 * @Size(min=, max=): 길이를 제한할 때 사용됩니다.
 * @Email: 이메일 형식을 검사합니다. 다만 ""의 경우를 통과시킵니다

package com.org.test.dto;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

import lombok.Data;

@Data
public class MemberDto {

	@NotEmpty
	private String name;
	
	@NotEmpty
	@Size(min = 4, max = 8)
	private String password;
	
	@NotEmpty
	private String email;
	
}

 

 

#파라미터 값들이 정상적으로 넘어왔을 경우 반환값입니다.

-정상적으로 통신이 됐다는 200 코드와 함께 데이터들을 반환받았습니다.

 

 

#파라미터값들이 유효성검사에서 실패한 경우 반환값입니다.

-실패를 의미하는 400 코드와 함께 에러 메시지를 반환받았습니다.

-password는 4자 이상 8자 이하로만 유효하게 설정해 놨는데 password 값을 3자리로만 보냈을 경우 아래와 같이 password가 벨리데이션에 실패했다는 것을 의미하는 데이터들을  반환되게 됩니다.

{
    "timestamp": "2023-04-02T14:41:54.208+00:00",
    "status": 400,
    "error": "Bad Request",
    "trace": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<com.org.test.dto.Message> com.org.test.controller.MemberController.insertMember(com.org.test.dto.MemberDto): [Field error in object 'memberDto' on field 'password': rejected value [123]; codes [Size.memberDto.password,Size.password,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [memberDto.password,password]; arguments []; default message [password],8,4]; default message [크기가 4에서 8 사이여야 합니다]] \r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:141)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:528)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:596)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:833)\r\n",
    "message": "Validation failed for object='memberDto'. Error count: 1",
    "errors": [
        {
            "codes": [
                "Size.memberDto.password",
                "Size.password",
                "Size.java.lang.String",
                "Size"
            ],
            "arguments": [
                {
                    "codes": [
                        "memberDto.password",
                        "password"
                    ],
                    "arguments": null,
                    "defaultMessage": "password",
                    "code": "password"
                },
                8,
                4
            ],
            "defaultMessage": "크기가 4에서 8 사이여야 합니다",
            "objectName": "memberDto",
            "field": "password",
            "rejectedValue": "123",
            "bindingFailure": false,
            "code": "Size"
        }
    ],
    "path": "/insert"
}

 

 

 

728x90
반응형

댓글