전역으로 유효성 검사를 한다고? (24.05.20)

YJ·2024년 5월 20일
post-thumbnail

블로그 작성법
목표 > 공부한 내용 > 얻었고, 앞으로 이걸 해봐야지 적기

✋ 수업 목표

  • 우리가 정의한 Response Format의 문제를 확인해보자.
  • @Validation
  • Errors 추가
  • @ExceptionHandler
  • JPA: DB Create
  • DataSource

🤔 공부한 내용

@Valid

import jakarta.validation.Valid;

Spring 3.x 버전을 사용하므로 jakarta가 사용된다.

  • NotNull: Null 만 안된다. "", " "(Blank)는 허용한다.

  • NotEmpty: Null과 ""만 안된다. " "(Blank)는 허용한다.

  • NotBlank: Null, "", " " 셋 다 안된다.

  • Email 정규 표현식

@Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,6}$", message = "이메일 형식에 맞지 않습니다.")

참고 자료
https://velog.io/@vpdls1511/Spring-Validator

Spring Boot의 공통 프로세스 처리

ExceptionResolver

  1. ExceptionHandlerExceptionResolver
  • MemberController : 메소드(핸들러)
  • @ExceptionHandler/@ResponseStatus
  • @ExceptionHandler : 스프링아, 아래 메소드는 예외가 터졌을 때 호출되는 메소드야

업그레이드
등록하는 모든 컨트롤러는 다 중복 메소드 생길 것 같아
-> 해결 방법은??

  1. ResponseStatusExceptionResolver : 상태 코드 적용 예외 처리
    사용자 예외 클래스 + @ResponseStatus(code="")

  2. DefaultHandlerExceptionResolver : 스프링 내부적으로 기본 예외 처리
    ex> JSON -> DTO 타입이 안 맞을 때
    TypeMismatchException 500 > 400
    아니 DTO 하나 잘못 되었는데

필터까지 올라가서 400으로 처리해줘야해?

(@Valid @RequestBody MemberDto memberDto, Errors errors)

필터까지 올려주지 말고 에러를 컨트롤러에서 잡기 위해
Errors를 매개변수로 받는다.

public ApiUtils.ApiResult<String> join(@Valid @RequiredBody MemberDto memberDto, Errors erros) {
	if(errors.hasErrors()) {
    	Map<String, String> errorMessage = new HashMap<>();
    	
        for(FieldError error : errors.getFieldErrors()) {
        	String errorField = error.getField(); // 예외 field 명
            String errorMessage = error.getDefaultMessage(); // 예외 message
            errorMessages.put(errorField, errorMessage);
        }
        
        return error(errorMessages, HttpStatus.BAD_REQUEST);
    }
}

=> 굳이 거기까지 올라가? 내가 그냥 Controller에서 처리할게
"@Valid 뒤에 Errors erros에 담아줘"
아쉬운 점
1. Status Code 티내기
2. message가 String이네? 프론트엔드에서 , 기준으로 parsing 해야할 탠데?

Map을 반환하는 2가지 방법

아쉬운점 (2) ApiUtils의 error(String)을 변환해보자.

해결 방법

  • ApiUtils의 error(String) / error(Map) 오버로딩
  • 제네릭 메소드를 사용

ApiUtils.class

public class ApiUtils {
    public static <T> ApiResult<T> success(T data) {
        return new ApiResult<>(true, data, null);
    }

    public static <M> ApiResult<M> error(M message, HttpStatus httpStatus) {
        return new ApiResult<>(false,
                null,
                new ApiError<>(message, httpStatus));
    }
    
     @Getter
    @AllArgsConstructor
    public static class ApiResult<T> {
        boolean success;
        T response;
        ApiError error;
    }

    @Getter
    static class ApiError<M> {
        M message;
        HttpStatus httpStatus;

        ApiError(M message, HttpStatus httpStatus) {
            this.message = message;
            this.httpStatus = httpStatus;
        }
    }

Controller Advice

@ModelAttribute
: Spring에서 풀스택을 개발할 때 사용하는 어노테이션

@ExceptionHandler
: 특정 메서드를 전역으로 사용하고 싶다면 해당 어노테이션을 사용하자

ControllerAdvice vs RestControllerAdvice

RestControllerAdvice는 ResponseBody를 사용한다.

참고 자료
https://docs.spring.io/spring-framework/reference/web/webflux/controller/ann-advice.html

log를 찍는 위치

  1. 매개변수가 잘 들어왔는지 검사
  2. iterator 등 객체 또는 변수를 하나씩 꺼내볼 때
  3. 클라이언트에게 전달하기 전

JPA, Security

Security는 Spring Boot v2로 진행할 것이다.

JDBC의 기본

DataSource 객체

  • 디비 속성값을 들고, (자바-디비) 터널을 뚫어준다.
  • SQL 소통이 가능하게 도와준다.

properties에 디비 속성값만 적어주면, Spring이 DataSource 객체 알아서 만들어준다!

DB Schema

  • Member Table
    Create
    SQL 실행 : 툴 vs CLI(서버)

  • 프로젝트 폴더: shoppingmall.sql

  • 데이터베이스 : 프로젝트명

  • Member Table (Entity)
    CREATE TABLE member (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id VARCHAR(255) NOT NULL,
    pw VARCHAR(255) NOT NULL,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    contact VARCHAR(20) NOT NULL
    );

면접 질문
Q1. 왜 그 자료형을 잡았을까?
SMALLINT vs BIGINT
컬럼 변경, 스키마 변경 시점?
Q2. VARCHAR( ___ )
Q3. 제약조건
Q4. 컬럼명 통일감, 테이블명 복수/단수
Q5. 연관 관계

DB 연결 방법

스프링(자바) 프로젝트

DataSource

JDBC의 객체

  • 인터페이스 (구현체 : hikari)
  • 터널 뚫고, sql 보내고 답을 받을 수 있음
  • 스프링이 properties 보고 자동으로 빈 생성
    1) JDBC dependency에 이 기능이 들어 있는 걸까?
    = JDBC dependency에 이 기능이 들어 있네

개인화된 금융서비스를 제공하기 위한 클라우드 MSA 환경 구축 및 서비스 개발

중간발표, 결과물
주제 겹치면 안됨, 선착순

DART API, 데이터 활용
재무제표, 투자상품 데이터 시각화
개인화 "추천" 연계

알쓸 송잡

개인 프로젝트 vs 팀 프로젝트
요새는 갠플 >===== 팀플 수준이다.
즉, 갠플을 해보는 것이 좋다.

어노테이션 하나하나까지 모든 기능을 알고 써야지 의미가 있다.

* 개인 프로젝트
개인 프로젝트는 mybatis를 추천한다.
3주~1달, 주제 x 간단하게!! 하나하나 다 알고 했다 + 블로그 카테고리
=> 블로그 카테고리 링크 제출

프로젝트 관리, 기술 선택권(이유)

* 팀 프로젝트
협업, 팀 단위 이슈, 선택(선택을 팀 단위로 했다.)

* 주제 창의성? 없다.

* 깃허브 :
- 프로필 레포 리드미: 내 자랑 플젝 레포 개요, 기술 스택, 나 표현하는 형용사 한 줄
(가독성) 링크 누르지 않고 이 프로젝트가 무슨 프로젝트인지 설명(너무 자세하면 안 읽힌다.)
cf. 링크 최소화

- 각 레포
	- 리드미 : 설계(패키지 구조, ERD(좀 신경 쓴 ERD - 고민 많이 한 ERD를 짚어주기)), PR 중 괜찮았던 & 질문 받고 싶은 내용, 회고 한~두 줄(블로그)
	- 커밋 메세지, PR(구현 기능, 이슈, 해결, 다음 계획, 커밋 메세지 - 자세히) 링크

😉 앞으로 이걸 해봐야지

오늘은 전역으로 유효성 검사를 진행하고, JPA를 설치하는 것 까지 진행하였다. 앞으로는 DB에 Map으로 데이터를 저장하는 것이 아니라 mysql을 설치하여 데이터를 저장해볼 것 이다. 재밌을 것 같다.

profile
dev

0개의 댓글