Coding

    [Spring Security] Filter에서 JWT 예외 처리

    [Spring Security] Filter에서 JWT 예외 처리

    현 프로젝트에서는 Spring에서 제공하는 @ControllerAdvice 어노테이션을 사용하여 전역 예외 처리를 하고 있으며, @ExceptionHandler를 통해 각 Custom Exception에 상응하는 status code를 내려주고 있다. 하지만 Filter에서 발생하는 JWT 예외는 위와 같은 방법으로 처리할 수 없다! Why Filter와 @ControllerAdvice는 서로 다른 컨텍스트에서 동작한다. 위의 그림을 통해 볼 수 있듯이 Filter는 Spring Context의 앞단인 Servlet Context에서 관리되는 영역으로, Spring에서 제공하는 @ControllerAdvice와는 예외 처리 메커니즘이 분리되어 있다. 따라서 Filter에서 발생하는 예외는 전역 예외 처리..

    [JPA] @OneToOne, 일대일(1:1) 연관관계 매핑 시 주의할 점 (지연 로딩 이슈)

    [JPA] @OneToOne, 일대일(1:1) 연관관계 매핑 시 주의할 점 (지연 로딩 이슈)

    문제 JPA를 사용하며 테스트를 통해 실제 수행되는 쿼리를 수시로 체크하는데, 일대일(1:1) 양방향 연관관계를 지니는 테이블에서 FetchType.LAZY가 적용되지 않아 불필요한 쿼리가 호출되는 것을 발견하였다. 아래는 문제가 되는 SHELTER와 SHELTER_USER의 연관관계 다이어그램이다. SHELTER와 SHETLER는 1:1 양방향 연관관계로 매핑되어 있으며, 대상 테이블인 SHELTER_USER에 외래키를 두고 있다. 문제는 SHELTER를 조회 시 SHELTER_USER 테이블도 즉시 로딩되어 아래와 같이 쿼리가 두 번 호출된다. 2023-08-11T17:58:58.461+09:00 DEBUG 2272 --- [nio-8080-exec-3] org.hibernate.SQL : /* */..

    [Spring] @JsonInclude와 @JsonIgnore

    지난주 프로젝트 모임 중 지현님께서 양방향 연관관계가 있는 Entity가 Json으로 변환될 때 순환 참조가 일어나는 에러가 발생하여 @JsonIgnore 어노테이션으로 문제를 해결하셨다는 얘기를 전해들었다. 당시 "저희 프로젝트에도 @JsonIgnore 사용한 코드 있어요!" 하고 찾아보니 @JsonInclude였다. response 반환 시 null 필드를 생략하기 위해 @JsonInclude를 사용했었는데, @JsonIgnore와 헷갈렸다. 헷갈리지 않도록 Jackson 어노테이션들을 살펴보고 정리해보고자 한다. Jackson Property Inclusion Annotations Jackson 라이브러리에서 사용되는 속성 포함에 관련된 어노테이션들로, JSON 직렬화 및 역직렬화 과정에서 특정 필..

    [AWS S3] 여러 객체 삭제

    [AWS S3] 여러 객체 삭제

    게시글 삭제 시 게시글에 첨부된 이미지/비디오/음성녹음 등 S3에 저장된 파일객체들을 모두 삭제해야 한다. 프로젝트의 S3 폴더 구조는 위와 같이 되어 있는데, boardKey 하위의 객체들을 한 번에 삭제하고 싶었다. 코드 public void delete(String base) throws IOException { var listObjectsV2Result = amazonS3Client.listObjectsV2(bucket, base); for (var objectSummary : listObjectsV2Result.getObjectSummaries()) { System.out.println("key = " + objectSummary.getKey()); amazonS3Client.deleteObje..

    [20230628] 오늘의 삽질

    오늘의 삽질📢 기존 코드는 아래와 같이 되어 있으며, 내 역할은 resize 메서드에서 리사이징 된 동영상의 바이트를 갖는 새 VideoCustomFile 객체를 반환하는 것이었다. @Getter public class VideoCustomFile implements CustomFile { private final byte[] bytes; private final String base; private final String fileName; public VideoCustomFile(MultipartFile multipartFile) { this.fileName = addRandomValueFilePrefix(multipartFile); this.base = "video"; try { this.bytes ..