본문 바로가기

분류 전체보기

(87)
[validation] @RequestParam으로 들어오는 파라미터의 exception handling / @RequestBody로 들어오는 객체의 exception handling @RequestParam과 @RequestBody는 같은 어노테이션을 사용하지만, 신기하게도 exception이 다르게 발생한다. 주로 발생하는 exception을 정리하고, 어떻게 handling 할 지 알아보겠다. @RequestParam 1. MissingServletRequestParameterException 필수적인 파라미터가 존재하지 않는 경우 해당 exception이 발생한다. 기본적으로 파라미터에 대해 required option이 true로 되어있기 때문에, RequestParam을 적용하고 파라미터를 넣어주지 않았다면 발생할 exception이다. [ErrorCode] INVALID_INPUT_VALUE(400, "COMMON-001", "유효성 검증에 실패한 경우") 2. Metho..
[validation] @RequestParam에서 @NotNull, @NotEmpty, @NotBlank를 어떻게 사용할 것인가 @NotNull과 @NotBlank의 차이가 뭔지 살펴보고, 적용해보고 있었다. 그러던 중No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.Integer'. 이라는 에러가 발생했고, 검색 결과 @NotBlank(또는 @NotEmpty)는 String 타입에 대한 validation annotation이였다. 만약 null값을 허용하고 싶지 않다면, @NotNull을 넣어주어야 한다. 그런데 여기서 생각해볼 문제가 하나 더 있다. "굳이 @RequestParam을 사용하는 곳에서 @NotNull이 필요한가?" 잘 생각해보면 필요하지 않다는 것을 알 수 있다. R..
[Error] java equals 사용 시 NPE 해결하는 습관 isDeleted field에, "Y", "N", null 값만 들어올 수 있도록 지정했기 때문에, NPE가 생기는 것이 이상해서 debugging을 진행하였다. 문제는, isDeleted field의 값을 체크하는 것을 null부터 하지 않았던 것이였다. null일 경우에, 이미 앞에서 equals 메소드를 진행할 때 NPE가 나버리기 때문이다. 앞에서부터 차례로 조건을 확인한다는 것을 기억하자. 코딩테스트에서도 비슷한 경우가 있다. plain에 대한 bfs를 진행할 때, plain의 범위 안에 들어있는지 확인한 후 방문 여부를 확인한다(0
[ERROR] JSON parse error: Cannot deserialize value of type `java.time.LocalTime` from String [기본개념] deserialize : 역직렬화 - JSON을 Java 타입으로 변환하는 과정 [Jackson] spring-boot-starter-web dependency를 추가하면, 그 하위에 json객체를 파싱해주는 spring-boot-starter-json 라이브러리가 기본으로 탑재되어있다. 그 하위에는 jackson 라이브러리들 (jackson-datatype-jsr310 라이브러리 포함)이 존재한다. Jackson 라이브러리의 @JsonFormat 어노테이션을 활용해서, 해당 오류를 해결하면 된다. 1. RequestBody로 들어온 json을 파싱하기 컨트롤러에서는 @RequestBody를 통해 request 객체를 받는다 @PostMapping("/api/requested-store/re..
[Gradle] dependency의 version을 명시하기 vs 생략하기 스프링부트와 gradle을 사용할 때, dependency를 추가한다. 이때, 버전을 적는 경우가 있고 안적는 경우가 있다. 버전 적는 경우 특정 버전을 명시하고 싶을 때 애매하다 싶으면, 이렇게 적어야한다. (실제로 버전 안적어서 컴파일 오류 발생했었음) compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' 버전 안적는 경우 dependency를 가져오는 저장소에서 가장 최신 버전을 가져온다 annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
[Spring] AOP AOP 부가기능을 똑 떼어서, 재사용하기 위한 것이다. 인프라 로직 (부가기능) 애플리케이션의 전 영역에서 나타날 수 있다 중복 코드를 만들어 낼 가능성 - 유지보수 힘들어짐 비즈니스 로직과 함께 있으면, 비즈니스 로직을 이해하기 어려워진다 비즈니스 로직 위에 횡단으로(가로로) 같은 로직들이 위치해있기 때문에, 인프라 로직은 횡단 관심사라고도 불린다. AOP (Aspect Oriented Programming) 관점 지향 프로그래밍. 즉, 횡단 관심사에 따라 프로그래밍 한다고 생각하면 된다. 자바에서는 AspectJ 라는 구현체로 AOP가 구현되어있다. 부가기능을 똑 떼어서, 재사용하기 위한 것이다. 그럼, 1. 어떤 부가기능을, 2. 언제, 3. 어디에 사용해야할까? 1번과 2번 -> Advice로 정..
[Spring] 스프링으로 파일 업로드, 다운로드 구현하기 (3) - DB까지 사용하여, 실제로 파일 업로드와 다운로드 해보기 지금까지는 업로드에 대해서 알아보았다. 실제 DB에도 저장하지 않았다. 실제로 파일을 업로드, 다운로드 하기 위해서는, 파일의 내용을 저장하는 DB까지 필요하다. 이제, 실제 예시를 통해 파일 업로드와 파일 다운로드 방법을 알아보자. [개념] 파일 업로드란? 파일 업로드라는 것이 파일을 바이너리 데이터로 만들어서 DB에 넣어둔다는 뜻이 아니다. 비싼 저장장치인 DB를 이미지 저장소로 사용하지는 않는다. 우리는 DB에 파일의 정보(파일 이름, 파일이 서버에 저장되었을 때의 이름, 컨텐트 타입, 등록 날짜, 수정 날짜 등등)만을 저장할 것이다. 파일이라는 데이터 그 자체는, 서버에 올라가게 된다(현재는 작업을 로컬에서 진행하므로, 내 로컬 저장소(하드디스크)가 그 역할을 하게 된다) 정리하자면 파일 업로드란..
[Spring] 스프링으로 파일 업로드, 다운로드 구현하기 (2) - multipartFile 이용하기 김영한님 강의에서는 서블릿으로 파일을 전송하는 방법을 설명한 후에, 스프링으로 파일을 전송하는 방법에 대해 설명한다. 결국 스프링으로 파일을 전송하는 것을 사용하므로, 이에 대해서만 소개하겠다. 스프링은 메서드의 파라미터로 MultipartFile 타입을 지정하면, 파일을 받을 수 있도록 만들어두었다. 아래의 코드를 보면, 빠르게 이해할 수 있다. @Value("${file.dir}") private String fileDir; // 파일을 저장할 경로. 해당 경로에 폴더가 만들어져 있어야 한다. @PostMapping("/upload") public String saveFile(@RequestParam String itemName, // MultipartFile로 file을 전송받기 @RequestPa..
[Spring] 스프링으로 파일 업로드, 다운로드 구현하기 (1) - multipart/form-data란 무엇인가? 스프링은 HTML Form을 이용해 서버로 데이터를 전송하게 된다. HTML Form 전송방식에는 2가지가 있는데, 다음과 같다. application/x-www-form-urlencoded multipart/form-data 1번은 서버로 데이터를 전송하는 가장 기본적인 방법이다. Form으로 데이터를 전송할 때(post요청) 별도의 enctype 옵션이 없으면 웹 브라우저는 요청 HTTP 메시지의 Header에 [ Content-Type: application/x-www-form-urlencoded ] 를 추가한다. 그 다음, Body에 폼에 입력한 전송 데이터를 문자로 username=kim&age=20 와 같이 &로 구분하여 전송하게 된다. 2번은 파일을 업로드 할 때 사용하는 방식이다. 파일은,..
[Gradle] implemetation, api, complieOnly, runtimeOnly Gradle의 Dependency 4가지 classpath는 클래스나, jar 파일이 존재하는 위치라고 볼 수 있다. compileClassPath : 에러없이 컴파일을 하기 위해 필요한 클래스와 jar들의 위치를 나타낸다(주의할 점은, 컴파일이 완료되었다고 애플리케이션이 정상적으로 실행되는 것이 아니다) runtimeClassPath : 애플리케이션이 정상적으로 실행하기 위해 필요한 클래스들과 jar들의 위치를 나타낸다. 우선, complie time과 runtime에 대해 알아보자. 컴파일 타임 & 컴파일 타임 에러 코드가 컴파일을 통해 기계어로 변환되는 과정이다. 컴파일 타임 에러는 코드 상의 구문 오류 또는 누락된 파일을 참조하는 것과 같은 문제로 인해 프로그램이 성공적으로 컴파일되지 못하는 상황..