본문 바로가기

분류 전체보기

(89)
[코드트리] 코딩테스트 대비를 위한 갭체크 후기 - 시뮬레이션 코드트리 갭체크를 통해 제가 부족한 알고리즘 유형을 확인했고, 이번에는 시뮬레이션 영역에서 보완이 필요하다는 결과를 받았습니다. 시뮬레이션 문제는 주어진 조건을 그대로 코드로 옮기는 유형이라고 생각했지만, 실제로는 날짜와 시간 계산, 진법 변환, 구간 길이 계산, 직사각형 넓이 계산처럼 세부 조건을 정확히 해석하고 빠뜨리지 않는 능력이 중요하다는 점을 알게 되었습니다.특히 제가 부족하다고 느낀 부분은 문제의 요구사항을 단계별로 쪼개는 과정입니다. 시뮬레이션 문제는 복잡한 알고리즘을 몰라도 풀 수 있는 경우가 많지만, 조건이 많아질수록 예외 상황을 놓치기 쉽습니다. 예를 들어 시간 계산에서는 기준 시점을 어떻게 잡을지, 날짜가 바뀌는 경우를 어떻게 처리할지까지 생각해야 합니다. 구간이나 직사각형 문제도 단..
[코드트리] 코딩테스트 대비를 위한 갭체크 후기 최근 코드트리의 캡체크를 진행하면서 제 현재 실력을 객관적으로 확인해볼 수 있었습니다. 단순히 문제를 푸는 것에서 끝나는 것이 아니라, 어떤 개념이 충분히 잡혀 있고 어떤 부분이 아직 약한지를 한눈에 볼 수 있어서 꽤 유익했어요. 특히 이번 결과를 보면서 “아는 것 같았던 개념도 실제로는 완전히 내 것으로 만들지 못했구나”라는 점을 많이 느꼈습니다. 전체적으로는 출력, 단순 반복문, 조건문 같은 기본 개념은 비교적 안정적으로 해결할 수 있었습니다. 이런 문제들은 손이 먼저 나가는 편이라 크게 막히지 않았고, 문제를 읽고 바로 코드로 옮길 수 있었습니다. 반면 조건문 응용이나 1차원 배열처럼 조금만 구조가 복잡해지는 문제에서는 생각보다 더 많은 시간이 필요했습니다. 개념 자체를 모른다기보다, 상황에 맞게 ..
[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..