7/15, 7/16 스프링 MVC : 커맨드 객체 검증, 세션, 쿠키

박세현·2024년 7월 15일

Spring

목록 보기
10/15
post-thumbnail

스프링 MVC

1. 커맨드 객체 검증

1) Validator 인터페이스

① supports(...)

  • 검증하는 커맨드 객체 한정 설정

② validate(Object target, Errors errors)

  • 커맨드 객체 검증
    • 매개변수
      • Object target : 커맨드 객체 -> -> 형변환
      • Errors errors : 검증 실패 시 전달할 메세지 등록...

예시)

ㄴ hasErrors() : 한개라도 reject 또는 rejectValue가 호출되면 true = 검증 실패했다는 말

ㄴ 포스트로 바뀌었음에도 검증에서 걸려서 넘어가지 않는 모습

ㄴ 여기서 걸림

ㄴ 검증 잘 통과하면 로그인 페이지로 넘어가는 모습

ㄴ 스크립트로 에러메세지 보여주는게 아니라 바로 나오는 에러메세지

ㄴ 이렇게



예시) 에러코드 넣기

ㄴ 공통/에러/유효성 으로 분리해서 관리
ㄴ 연동 설정 : 메세지 소스라는 빈에 정의(인터페이스)

ㄴ 연동 설정 : 메세지 소스라는 빈에 정의(인터페이스)

ㄴ rejectValue("필드명", "에러코드", "기본메세지"); : "기본메세지" : "에러코드"가 없을때 나오는 문구
ㄴ "에러코드" 문구가 나옴

ㄴ 범위 한정하기

ㄴ 네입값이 필드명이다!!! = 전송하는 항목
ㄴ 양식은 데이터를 전송하는 목적인데 네임속성을 가지고 전송 (아이디가 아니다!!!)

ㄴ 필드명, 에러코드, 기본메세지
ㄴ 기본메세지 : 에러코드가 정의된게 없을 때 나오눈 문구

ㄴ 약관동의 : 에로코드.커맨드객체.필드명으로 한정
ㄴ 약관동의는 어떤 약관인지에 따라 문구가 다르기 대문에 더더 한정



예시) 검증 추가_이메일 중복한지, 비밀번호 자리수 체크 등등...

ㄴ 에러코드.필드명
ㄴ 에러코드.커맨드객체명.필드명



예시) Bean Validation

ㄴ 이렇게 정의 잘 안함
ㄴ 이렇게 많이쓰는 검증은 Bean Validation에 이미 있음 애노테이션통해 알려주기만 하면 됨

2) Errors

① reject() : 특정필드❌

  • 커맨드 객체 자체 오류에 대한 처리 = 특정필드❌
    • reject("에러코드");
    • reject("에러코드", "기본 메세지")

② rejectValue() : 특정필드⭕

  • 커맨드 객체의 특정 필드 오류에 대한 처리 = 특정필드⭕
    • rejectValue("필드명", "에러코드");
    • rejectValue("필드명", "에러코드", "기본메세지");
      • "기본메세지" : "에러코드"가 없을때 나오는 문구

③ hasErrors()

  • 한개라도 reject 또는 rejectValue가 호출되면 true = 검증 실패했다는 말

참고) String Utils

  • 문자열 관련된 편의 기능

참고) 타임리프
#fields.errors("필드명") : -> errors 객체 담긴 메세지를 필드명으로 조회 -> 배열


<form:errors path="필드명" />

  • 기본 에러 출력 태그 span, 여러 에러 메세지가 있는 경우 <br> 구분(delimiter)
  • element="태그명"
  • delimiter="에러와 에러 메세지 사이에 추가할 태그" = 기본값이 div태그



3) ValidationUtils

  • 필수 항목 검증에 편의 메서드
  • rejectIfEmpty(...) : null또는 ""
  • rejectIfEmptyOrWhitespace(...) : 공백 포함 체크

예시)

ㄴ 이거 너무 길다

ㄴ 근데 이거보다 더 좋은거 있어서 이것도 사용거의 안 할 예정...

2. 에러 코드에 해당하는 메시지 코드를 찾는 규칙

  • 에러코드 + "." + 커맨드객체이름 + "." + 필드명
  • 에러코드 + "." + 필드명
  • 에러코드 + "." + 필드타입
  • 에러코드

예시) 에러코드 넣기

ㄴ 공통/에러/유효성 으로 분리해서 관리
ㄴ 연동 설정 : 메세지 소스라는 빈에 정의(인터페이스)

ㄴ 연동 설정 : 메세지 소스라는 빈에 정의(인터페이스)

ㄴ rejectValue("필드명", "에러코드", "기본메세지"); : "기본메세지" : "에러코드"가 없을때 나오는 문구
ㄴ "에러코드" 문구가 나옴

ㄴ 범위 한정하기

ㄴ 네입값이 필드명이다!!! = 전송하는 항목
ㄴ 양식은 데이터를 전송하는 목적인데 네임속성을 가지고 전송 (아이디가 아니다!!!)

ㄴ 필드명, 에러코드, 기본메세지
ㄴ 기본메세지 : 에러코드가 정의된게 없을 때 나오눈 문구

ㄴ 약관동의 : 에로코드.커맨드객체.필드명으로 한정
ㄴ 약관동의는 어떤 약관인지에 따라 문구가 다르기 대문에 더더 한정




3. 프로퍼티 타입이 List나 목록인 경우 다음 순서를 사용해서 메시지 코드를 생성한다.

  • 에러코드 + "." + 커맨드객체이름 + "." + 필드명[인덱스].중첩필드명
  • 에러코드 + "." + 커맨드객체이름 + "." + 필드명.중첩필드명
  • 에러코드 + "." + 필드명[인덱스].중첩필드명
  • 에러코드 + "." + 필드명.중첩필드명
  • 에러코드 + "." + 중첩필드명
  • 에러코드 + "." + 필드타입
  • 에러코드



4. 글로벌 범위 Validator와 컨트롤러 범위 Validator

1) 글로벌 범위 Validator 설정과 @Valid 애노테이션

  • WebMvcConfigurer의 getValidator()
  • 모든 컨트롤러의 공통적인 검증이 필요한 경우

예시)

ㄴ 이거 없어도 이미 전역에 밸리데이터 적용해서 실행 됨
ㄴ @밸리드 : 이걸 보고 전역에 적용할 검증 찾아냄

ㄴ 이거 전역밸리데이터



2) @InitBinder 애노테이션을 이용한 컨트롤러 범위 Validator

@InitBinder
protected void InitBinder(WebDataBinder binder) {
	binder.setValidator(new RegisterRequestValidator());
}
  • 특정 컨트롤러에서 사용할 공통적인 Valdiator

예시)

![]

ㄴ 검증 성공 후 서비스 처리하는 로직



3) 컨트롤러 범위 Validator > 글로벌 범위 Validator




5. Bean Validation

  • 기본검증해주는 의존성
    ex) 이메일 중복여부, 비밀번호 자리수 체크 등등
  • Bean Validation API
    • implementation 'jakarta.validation:jakarta.validation-api:3.0.2'
  • hibernate Validator (Bean Validation API의 구현체)
    -> 알려주면 알아서 검증해준다(기본적인 검증 거의 다 해준다, 여기서 안해주는 검증만 밸리데이터 정의해주면 됨)
    • implementation 'org.hibernate.validator:hibernate-validator:8.0.1.Final'
      -> 3.0.2버전으로 Bean Validation API 써야 함
    • 이거 추가하면 Bean Validation API 굳이 따로 추가안해도 되긴 함
    • 의존성에 의존성으로 자동 추가됨


1) 설정

참고

ㄴ 자바x인지
ㄴ 자카르타인지 체크하고 의존성 추가하기



2) Bean Validation의 주요 애노테이션

  • @AssertTrue

  • @AssertFalse

  • @DecimalMax

  • @DecimalMin

  • @Max

  • @Min

  • @Digits

  • @Size

  • @Null

  • @NonNull

  • @Pattern

  • @NotEmpty

  • @NotBlank

  • @Positive

  • @PositiveOrZero

  • @Email

  • @Future

  • @FutureOrPresent

  • @Past

  • @PastOrPresent

ㄴ 낫블랭크 : 필수항목검증 // 가장 많이 사용할 것
ㄴ 이메일 : 이메일 형식 체크

3) 커맨드 객체 검증

① Bean Validation API - 애노테이션으로 기본검증 처리

  • 애노테이션명이 에러코드임

② 기본 애노테이션으로 안되는 검증 Validator를 정의

예시) Bean Validation + 기본 애노테이션으로 안되는 검증 Validator를 정의

ㄴ 이렇게 정의 잘 안함
ㄴ 이렇게 많이쓰는 검증은 Bean Validation에 이미 있음 애노테이션통해 알려주기만 하면 됨

ㄴ 주석함

ㄴ 이 커맨드 객체가 검증대상이라는 걸 알려줘야 함

ㄴ @Valid : 이 커맨드 객체가 검증대상이라는 걸 알려줌

ㄴ 검증 실패 시 errors객체에 담아줌
ㄴ 무조건 커맨드 객체 바로 뒤에 에러객체가 있어야 담김!!!, 중간에 추가하거나 앞에오거나 등등 그러면 안담김
ㄴ 커맨드 객체 바로 뒤 = 에러객체!!!

ㄴ 기본메세지가 default로 설정되어 있고 그 메세지가 나온 모습

ㄴ 이걸 정의하면 사용자정의 메세지가 나옴

ㄴ 메세지 정의함
ㄴ 문구가 바뀜

ㄴ @빈 밸리데이터 에서 못하는 검증 빼고는 다 주석처리함

ㄴ 에러코드.필드명
ㄴ 애노테이션명=에로코드명





로그인

1. 컨트롤러

  • 로그인 URL 처리 메서드
    • @GetMapping - 양식,
    • @PostMapping - 처리 : /member/login



2. 커맨드 객체 검증 - RequestLogin

1) Bean Validation Api - 기본 검증

2) Validator 정의 검증

검증항목)
1) 필수 항목 검증 (이메일, 패스워드)
2) 이메일로 회원이 조회되는지 검증
3) 조회된 회원의 비밀번호가 입력한 값과 일치하는지 검증




3. 양식에 검증 실패 시 출력 메세지

ㄴ 맨밑에는 default라서 굳이 오버라이딩 안해도 됨
ㄴ 위에 2개는 무조건 오버라이딩 해야하는 추상메서드

ㄴ rejectValue = 보안성 취약 -> reject형태로

ㄴ 에러메세지가 아이디나 비번 옆에서 나오는게 아니라 커맨드 객체 그 자체에서 출력

ㄴ 이렇게 코드 쓰면

ㄴ 이 조건 식 필요 없음





4. 로그인 처리

1) 세션 생성 3가지방법

ㄴ 1. 요청이 오자마자 세션 생성

ㄴ 2.

ㄴ 3. 의존성으로 세션 생성

예시)

ㄴ 로그인 -> 메인페이지 -> 다시 로그인 창 감
ㄴ 세션이 유지되는 모습 쳌





스프링 MVC

1. 세션

  • 쿠키 : 브라우저
  • 세션 : 서버 (쿠키가 있어야 함 <- 세션 아이디를 부여)


1) @SessionAttribute("이름")

  • 세션값 조회 및 주입


2) @SessionAttributes(이름)

  • Model로 해당 이름으로 값을 속성으로 추가하면 세션에도 동일한 이름으로 추가
  • 세션에 해당 이름의 값이 있으면 Model에 자동 추가
  • Magic Form - 여러 페이지의 양식
  • SessionStatus
    • session.removeAttribute("이름");

ㄴ 제거된 세션


예시) @SessionAttribute("이름") : 세션 값 조회 및 주입

ㄴ 오류 발생

ㄴ 해당 세션이 없으면 오류 발생

ㄴ 로그인 -> 메인페이지 -> 다시 로그인 창 감
ㄴ 세션이 유지되는 모습 쳌

ㄴ 로그아웃



예시) 설문조사

ㄴ 여러개의 페이지로 구성된 양식
ㄴ 페이지 구성하고 커맨드객체 구성할거임

ㄴ 질문 2개/질문 2개/질문출력 이렇게 구성예정
ㄴ 컨트롤러쪽에 연동할거임

ㄴ 컨트롤러쪽에 커맨드 객체 연동
ㄴ 겟 방식일때는 모델어트리뷰트 해줘야함

ㄴ step1 뷰 구성

ㄴ step2 뷰 구성

ㄴ step3 뷰 구성

ㄴ 질문1,2 값이 안넘어옴



예시) 여러페이시 데이터 넘겨주기_히든

ㄴ 히든값으로 값 넘겨주기

ㄴ 이렇게 담겨있음
ㄴ 근데 이렇게는 하드 코딩임
ㄴ 질문이 100문항이면 어떡함
-> 세션어트리뷰트 : 모델쪽에 커맨드객체를 속성으로 넣어줌?



예시) 여러페이시 데이터 넘겨주기_세션어트리뷰트(매직 폼) = 양식에 있는 값을 유지할 때 활용

  • 예약페이지, 설문조사..이럴때 많이 사용
  • 마지막에는 셋컴플리트() 이용해서 세션을 비워주어야함 왜? 임시로 사용하는 거기 때문에

ㄴ 위에 이렇게 해서 아래 겟에 매개변수는 없애도 됨

ㄴ 동일하게 값 유지

ㄴ 요청쪽에 넣으면 알아서 객체가 주입된다?

ㄴ 상단 : 커맨드 객체
ㄴ 하단 : 세션

ㄴ 양식데이터에는 이거 없음

ㄴ 네임값이 없음 : 양식을 통해서 값이 넘어온게 아님
ㄴ 세션쪽에 q1,q2의 값이 있다

ㄴ 세션쪽에 값이 담겨있고
ㄴ 세션쪽에 있는 값을 커맨드 객체에 주입해줌

ㄴ 세션쪽에 값이 담겨있고
ㄴ 세션쪽에 있는 값을 커맨드 객체에 주입해줌
ㄴ 음 근데 세션 비운후에도 값이 유지되네

ㄴ 세션을 매번 가져오게 하면 찐 세션 비운 후에 값 나올거임
ㄴ 음 그래도 안되네ㅎ
ㄴ 나중에 하쟈




2.인터셉터

1) HandlerInterceptor 인터페이스

  • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
  • void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
  • void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;

ㄴ 시점 체크

ㄴ 프리핸들 시점 : 핸들러매핑 이후 핸들러 어댑터 이전

ㄴ 포스트핸들 : 핸들러어댑터 이후

ㄴ afterCompletion 시점


① preHandle

  • 컨트롤러빈이 실행되기 전 실행 = 컨트롤러 메서드 실행 전
  • 반환값 : boolean
  • 공통 값 유지 혹은 통제의 기능에 주로 사용하는 메서드
  • 왜 반환값이 불리언?
  • 반환값에 따라서 컨트롤러 빈의 메서드의 실행 여부 통제하기 위해서
    (관리자 페이지 접근, 회원전용 페이지 접근 등등...)
    • true : 컨트롤러 메서드 실행ㅇ
    • false : 컨트롤러 메서드 실행x


② postHandle

  • 컨트롤러가 실행된 후 = 모델엔뷰 반환 직후 = 컨트롤러에 있는 요청메서드가 실행 된 후 = 응답 전(?)


③ afterCompletion

  • 응답 후에 실행
  • 위 3개 다 default메서드라서 필요시에만 오버라이딩 하면 됨
  • 위 3개다 공통처리에 많이 사용 특히 preHandle()
    • 통제는 잘 안씀(따로 인증인가 프레임워크가 있어서)
    • 공통적인 처리에 많이 사용

ㄴ 반환값 쳌

ㄴ postHandle : 매개변수에 모델엔뷰 쳌

ㄴ afterCompletion : 매개변수에 에러 쳌


예시) 회원전용페이지

ㄴ preHandle 오버라이딩

ㄴ url가지고 인터셉트가 적용될 범위 설정하기

ㄴ 설정 추가함

ㄴ 인터셉트 적용 범위 설정

ㄴ 아직 안배워서 그렇지 이런식으로 통제 잘 안하고 있는 프레임워크 쓴다고...




2) WebMvcConfigurer 인터페이스 : addInterceptors(InterceptorRegistry registry)



3) Ant 경로 패턴

  • * : 0개 또는 그 이상의 글자
  • ** : 0개 또는 그 이상의 폴더 경로
  • ? : 1개 글자



3.쿠키

  • 만료시간이 있음
    • 이메일 기억하기...

1) @CookieValue

  • 개별 쿠키값 조회

예시)

ㄴ 쿠키값을 리퀘스트통해 조회한게 아니라
ㄴ 빈을 통해 조회?

예시) 7/16

ㄴ 쿠키가 저장된 모습

ㄴ req 메서드
ㄴ 쿠키 조회
ㄴ 아쉽지만 개별 쿠키조회메서드는 없음
-> 스프링 : @CookieValue : 개별 쿠키값 조회

profile
귤귤

1개의 댓글

comment-user-thumbnail
2024년 7월 15일

올라왔다! 돌격!

답글 달기