-
[스프링부트 및 JPA] - 전처리 후처리 개념 본문
지금까지 회원가입에 대한 기초적인 틀은 잡혔습니다.
이제부터 해볼 것은 예외상황 처리 과정입니다.
그림과 같이 서버, DB, JPA의 구조가 다음과 같을 때 사용자가 회원가입을 위해 username과 password 등을 Input한다고 해봅시다.
그런데 만약에 회원가입 시도 중 중복된 사용자에 대한 처리는 어떻게 해주는 것이 좋을까요?
회원가입할 때 username이 DB에 있는지 확인하는 루트는 서버 -> DB에 물어보는 방법밖에 없습니다.
그리고 사용자의 username을 20자로 제한하고 싶을 때 어떤 사용자가 20자 이상 입력해서 회원가입을 시도하려한다면 어떻게 막아야할까요?
이건 굳이 DB에 묻지 않더라도 서버의 앞단에서 미리 처리를 해줄 수 있습니다.
이것을 바로 전처리, 후처리 과정이라고 합니다.
자 그래서 그림으로 이해를 해봅시다.
여기 이 주황색 부분이 후처리 과정입니다.
username이 서버를 거쳐서, JPA를 거쳐서, DB까지 거치고 오류를 딱 띄워주는 과정만 처리하면 되겠죠?
하지만 username의 길이와 같은 제약조건 위반의 행위는 어떨까요
이 빨간색 부분만 확인하면 되는 것이지요.
이해되시나요?
즉, 주황색 부분은 후처리, 빨간색 부분은 전처리라고 합니다.
그러므로 전처리 과정은 앞으로 Validation의 유효성 검사로 확인해볼 거이고
후처리는 ExceptionHandler를 통해 처리해볼 것입니다.
"길이가 잘못됐네? 들어가면 안되는 글자가 있네??"이런 과정은 굳이 DB에 물어보지 않아도 알아서 처리를 해줄 수 있게 만드는 것 ! 이것을 전처리 과정이라고 이해하시면 되겠습니다.
그리고 "아이디를 쓰는 사람이 이미 있네? 너 이미 아이디 한 번 만들었네?" 처럼 DB에 물어봐야 알 수 있는 과정을 후처리라고 했습니다.
이런 전처리 후처리는 내가 지금 해야 할 공통의 로직을 위해서 존재합니다.
지금 내가 구현해야할 로직은 바로 회원가입 로직이고 이것을 "핵심 기능"이라고도 합니다.
또한 회원가입을 위해 존재하는 전처리, 후처리 과정을 "공통 기능"이라고 합니다.
없어도 물론 회원가입은 작동하지만 있어야 더 정상적으로 작동하죠
그래서 이 공통기능을 다른 용어로 AOP라고 합니다.
( Aspect Oriented Programming )
또한 전처리, 후처리 과정을 바로 코드에 넣는 것이 아니라 다른 클래스를 만들어서 관리하는 것이 상당히 편리하기 때문에 한 번 살펴보도록 하겠습니다.
전처리를 먼저 해보겠습니다.
1) 전처리
제일 먼저 https://mvnrepository.com/
여기로 이동합니다.
if else문으로 길이가 초과되었을 때와 아니었을 때를 구분해서 로직을 짜도 되지만 굉장히 무거워지기 때문에 우리는 Validation check를 위한 라이브러리를 이용할 것입니다.
거기서 Spring Boot Starter Validation의
에서 사용자 많은 것을 하나 복사합니다.
그리고 pom.xml의 dependencies안에 넣고 저장합니다.
자 그럼 어떤 기능을 이용할 수 있냐면
@AuthController에 파라미터로 @Valid를 걸면 이 SignupDto를 Validation 체크하게 됩니다.
그 다음에 SignupDto로 이동해서
username의 길이는 20으로 제한하고 네 개의 변수는 모두 NotBlank 즉, 무조건 입력을 받아야 하게끔 설정할 수 있습니다.
이후 DB에 넣는 User 클래스도 좀 손봐줘야 하는데,
User클래스에서도 우리가 email, username, pw을 모두 받을 것이기 때문에 nullable = false로 지정합니다.
왜 이렇게 하냐면 자 봅시다.
우리가 방금 SignupDto에서 손본 것은 전처리과정의 일환이었습니다.
근데 만약 어떤 사용자가 우리가 구현한 사이트에서 회원가입을 정상적으로 진행한다면 참 좋겠지만 어떤 다른 프로그램을 이용해서 길이도 20자가 넘고 email이나 pw같은 필수 기입요소를 기입하지 않고 기입한다면 어떤 일이 벌어질까요?
SignupDto는 회원가입할 때 사이트에서 들고가는 하나의 덩어리와 같습니다.
그리고 User는 DB에 Insert할 데이터 덩어리와도 같습니다.
둘 다 모두 입력받아야 할 필수 요소들은 이렇게 제약조건을 걸어서 사이트 내에서, 그리고 DB에 넣기 전 오류가 터지는걸 방지하기 위해 미리 막아놓는 것이라고 생각하면 되겠습니다.
User 클래스에서는 @Valid를 이용하지 않는 것은 DB에 Insert할 땐 @Column제약조건으로 막아야 하기 때문입니다.
이어서 진행하겠습니다.
@Valid 유효성 검사를 진행할 땐, 문제가 생겼을 때의 처리과정도 같이 처리해주어야합니다.
그래서
다음과 같이 입력해줍니다.
해석해보자면, @Valid SignupDto는 SignupDto는 유효성 검사를 진행하는데 그 검사는 SignupDto에서 제약조건을 걺으로써 진행했었습니다. 그리고 그 때 에러가 발생한다면 우리는 BindingResult라는 클래스를 이용해서 검사를 할 건데, bindingResult라고 객체를 생성합니다.
그리고 만약 bindingResult에 .hasErrors() -> 에러가 있으면
errorMap이라는 Map의 자료구조를 갖고오는데 <String,String> 타입이고
for문을 통해 error를 errorMap에 각각 error의 Field와 error의 Msg를 put시킵니다.
이렇게 하면 이제 반은 끝났습니다.
지금까지 한건 백엔드 단에서의 처리과정이었습니다.
그렇지만 제대로 제약조건을 걸어주려면 프론트단에서도 막아야 합니다.
그 과정은
이런식으로 jsp파일의 required = "required" 라고 입력해서 무조건 입력받아야 넘어갈 수 있게 짤 수 있습니다.
그럼 이렇게 누군가 얘기할 수도 있습니다.
프론트 단에서 다 막으면 되는데 굳이 백엔드에서 막는 이유가 있나요???
그 대답은 앞에서도 설명드렸습니다.
사용자 모두가 구현한 사이트 내에서만 회원가입할 수 있는 것이 아니라 다른 프로그램을 악용해서 회원가입을 할 수도 있습니다.
당장에 널리 보급된 Postman을 이용한다면 위에 있는 프론트단의 로직을 모두 무시하고 회원가입을 진행할 수도 있기 때문입니다.
이어서 진행하겠습니다.
AuthController로 가서 signup메서드 앞에 @ResponseBody String이라고 입력합니다.
이렇게 하게 되면 원래 우리가 이 AuthController를 @Controller라는 어노테이션까지도 달았다 하더라도 return할 때 데이터를 return할 수 있게 해줍니다.
그럼 이렇게 바꿔봅시다.
이 과정에서 분기가 필요합니다.
항상 에러가 나는 것이 아니기 때문에 에러가 나는 상황에 한해서만 if문을 실행시켜주는게 훨씬 깔끔하겠죠?
그리고 나중에 수정할 것이지만 return으로 "오류남"; 이렇게 입력해보았습니다.
또한 else문을 통해 회원가입이 정상적으로 이루어지면 return "auth/signin";을 리턴하여 login페이지를 응답합니다.
근데 이로 인해 문제점이 하나 생깁니다.
if문에서는 return이 String타입이고, else문에서는 return 타입이 jsp파일이잖아요?
이렇게 되면 굉장히 애매해질 수 있습니다.
따라서 하나로 통일을 해줘야 하는데 다음 포스팅에서 마저 안내해드리겠습니다.
'백엔드 기술 정리 > 스프링 부트' 카테고리의 다른 글
[스프링부트 및 JPA] - 공통 응답 DTO 만들어보기 (0) | 2022.02.11 |
---|---|
[스프링부트 및 JPA] - 예외를 고의로 생성하고 CustomExceptionHandler로 낚아채기 (0) | 2022.02.11 |
[스프링부트 및 JPA] - BCryptPasswordEncoder를 이용한 비밀번호 해시화 (0) | 2022.02.05 |
[스프링부트 및 JPA] - @RequiredArgsContructor과 @Autowired를 이용한 DI (0) | 2022.02.04 |
[스프링부트 및 JPA] - 사용자 모델 만들기 (0) | 2022.01.29 |