문제 파일 업로드 시 파일명에 '-', '_' 을 제외한 특수 문자 사용 시 예외를 발생시키는 코드에서 아래와 같은 정규표현식을 사용했고, 테스트 결과 문제가 없음을 확인했다. /^[ㄱ-ㅎ가-힣a-zA-Z0-9_\s-]*$/ 이후 파일명에 문제가 있는지 확인하기 위해 파일명과 똑같은 문자열을 비교하였으나, 다른 결과가 나왔고 문자열의 길이 또한 다르게 출력되었다. 원인 MacOS의 유니코드 정규화 인코딩 방식이 javascript의 기본 문자열과 다르기 때문이었다. Mac에서는 NFD 방식을 사용하는데, NFD 방식으로 작성된 문자열은 ['ㅎ', 'ㅏ', 'ㄴ', 'ㄱ', 'ㅡ', 'ㄹ']과 같이 초성, 중성, 종성으로 분리된 문자 배열이고 Javascript에 일반 문자열은 ['한', '글']과 같이 ..
Spring Boot에서 @Controller로 index.html을 반환해주는 기본적인 코드가 동작하지 않는 문제가 발생했다. 404로 로그를 봤더니 resource not found라는 문구가 보였다. 평소 thymeleaf나 mustache, JSP와 같은 템플릿 엔진을 사용해서 항상 html 파일을 templates 디렉토리 하위에 두었는데 template 엔진을 사용하지 않을 때는 html 파일을 static 폴더에서 찾기 때문에 발생한 에러였다. 그리고 static에서 찾을 때는 return "index.html"과 같이 .html을 붙여줘야한다. 이 부분은 아래 설정을 사용하면 return "index"; 로 사용할 수 있다. spring: mvc: view: suffix: .html 별 것..
서버에서 다음와 같은 DTO를 클라이언트에게 응답으로 보냈을 때 is가 생략되어 "check: false"로 응답이 들어오는 문제가 일어난다면 래퍼 타입인 Boolean 타입으로 변경해주어야 한다. @Getter public class Dto{ private boolean isChecked; } Boolean 타입으로 변경 시 해결되는 이유 JSON 변환 시Getter를 사용하기 때문에 Getter를 무조건 생성해야하는데, Boolean 타입을 사용하게 되면 Getter로 getIsChecked()가 생성되고, boolean 타입을 사용하면 getChecked()가 생성되기 때문에 이런 문제가 발생한 것 같다. 따라서 롬복을 사용하지 않고 getter를 직접 getIsChecked()로 생성해주면 boo..
EC2 프리 티어를 사용해서 프로젝트 파일을 빌드하다 보면 서버가 멈출 때가 많다. 그 이유는 프리 티어로 제공하는 t2.micro의 메모리 용량이 너무 낮기 때문인데, Virtual Memory인 스왑 메모리를 사용하면 디스크를 메모리 처럼 사용하여 메모리 부족 문제를 해결할 수 있다. 사용 방법은 AWS 공식 홈페이지에 자세히 나와있다. 짧게 요약하자면 다음과 같다. RAM 2GB 이하에서는 스왑 공간은 최소 32MB 이상이며 RAM 용량의 1배 크기로 잡는 것을 권장한다. 2~32GB에서는 4GB + (RAM - 2GB), 32GB 이상에서는 RAM 용량의 1배 t2.micro는 1GB이기 때문에 아래와 같이 2GB로 잡으면 된다. 1. 128MB를 16번 사용하여 2GB 정도의 용량을 사용한다. ..
JPA에서 쿼리를 실행하는 방법에는 4가지가 있다. 가장 중요한 JPQL과 QueryDSL이 있고, Criteria, 네이티브 쿼리 기능도 존재한다. JPQL 테이블 기준이 아닌 엔티티를 기준으로 쿼리를 작성하며, 실행 시점에 DB쿼리로 변환된다. JPQL은 실행 시점에 1차 캐시를 조회하지 않고 바로 플러시되는 특징이 있고, 조회된 객체는 1차 캐시에 저장되어 영속된다. 엔티티는 객체이기 때문에 선언을 해줘야 컨트롤 할 수 있다. 따라서 m이라는 별칭을 꼭 써주어야한다. SELECT m FROM Member m WHERE m.id = 1; 패치 조인 JPA에서 성능 최적화를 위해 제공하는 기능으로 연관된 엔티티나 컬렉션을 한번의 SQL로 함께 조회가 가능하다. 일반 조인을 사용할 경우 지연 로딩과 프록..
값 타입은 복잡한 객체를 단순하게 다루기 위한 개념으로 기본 값 타입, 임베디드 타입, 컬렉션 값 타입 세 가지가 있다. 기본 값 타입 엔티티에서 int, String과 같은 기본 타입과 래퍼 클래스이다. 기본 값 타입은 참조가 아니기 때문에 변경 시 깊은 복사로 값만 변경되어 추적이 불가능하다. 참조를 이용하는 값 타입은 변경 시 다른 엔티티의 필드도 바뀔 수 있어서 공유해서는 안되고, 불변 객체여야한다. 하지만 기본 값 타입은 안전하다. 래퍼 클래스는 객체이기 때문에 공유가 가능하지만, 불변 객체이기 때문에 안전하다. 임베디드 타입 새로운 값 타입을 직접 정의할 수 있다 = 엔티티 클래스 내부에 다른 클래스 타입을 가진 필드를 사용할 수 있다 좌표나 주소 같은 비슷한 성격의 필드를 클래스로 분리함으로..