Spring12 인터페이스 구현체 동적 선택을 활용한 리팩토링 개요 개인프로젝트를 진행하면서 클라이언트가 전송한 파일을 종류에 따라 외부 저장소와 내부 저장소에 나눠서 관리해야 하는 기능이 필요했습니다. 상품의 이미지들을 등록하는 기능에서, 이미지의 종류 혹은 크기에 따라 다른 저장소에 저장을 하는 기능입니다. 먼저, 저장소를 크게 내부 저장소와 외부저장소로 구분해서 서버 내부에 저장할 이미지와 서버 외부에 저장할 이미지로 분류하고 분류한 이미지를 처리할 서비스가 2개 필요합니다. 그리고 이미지를 등록할 때, 적절한 서비스를 동적으로 선택합니다. 다음에는 클라이언트가 등록할 상품의 이미지들을 전송하면, 이미지들을 각각 적절한 저장소에 저장하고, 클라이언트가 등록한 이미지들을 조회할 때는 이미지의 경로를 반환하고, 이미지를 요청하면 서버가 저장소에서 이미지를 가져와 .. 2023. 9. 7. [JPA Hibernate] 1:N 관계의 Entity Collection 참조 변경 문제 발생 JPA를 사용해 프로젝트 진행하는 과정에서 단방향 1:N의 관계를 가진 엔티티에서 참조하고 있는 필드의 값을 변경하려고 시도하다가 발생한 문제입니다. 상품의 이미지를 등록하는 기능을 구현하던 중이었습니다. 상품 엔티티와 이미지 엔티티는 1:N의 관계를 가지고 있고, 상품에서 이미지를 참조할 수는 있지만 이미지에서 상품을 참조할 수는 없는 구조입니다. 두 엔티티의 코드는 아래와 같습니다. @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "product") @Entity public class Product extends BaseTimeEntity { @EmbeddedId @Column(name = "product_.. 2023. 9. 6. AOP (Aspect Oriented Programming) AOP 란? AOP는 관점을 기준으로 다양한 기능을 분리하여 보는 프로그래밍을 의미합니다. 개발자가 프로그램의 기능을 구현할 때, 기능의 핵심적인 부분과 부가적인 부분으로 나누고, 각 부분을 분리하여 모듈화 하겠다는 의미입니다. 핵심적인 부분(관점) : 기능이 의미하는 핵심 비즈니스 로직 부가적인 부분(관점) : 핵심 로직은 아니지만, 기능에 필요한 부가적인 부분(로깅, 파일 입출력, DB 연결(JDBC) 등...) AOP 의 목적 우리가 주문 기능을 API 형태로 구현한다고 가정해 봅시다. 주문 기능을 구현하러면 구매한 상품, 구매한 상품들의 가격, 결제 등 주문의 핵심적인 부분과 주문 API를 요청했을 때, 주문을 처리하는 데 걸리는 시간, 주문을 구성하는 여러과정을 처리하는 도중 한 가지가 실패했을.. 2023. 9. 4. Spring Event를 활용한 Slack 메시지 전송 프로젝트 소개 Spring Event 기능을 활용해서 주문 시스템에서 주문이 발생하면, Slack에 '주문알람' 메시지가 전송되는 기능을 구현한 프로젝트입니다. REST API 만으로 구현했을 때 도메인계층에서 로직이 섞이는 부분이 있어서 Spring Event를 활용하면 로직이 도메인 계층에서 섞이지 않고, 주문했을때 문자메시지를 발송하는 기능과 같은 추가기능을 필요로 할 때도 확장이 용이할 것 같다는 생각에 구현해보았습니다. 요구사항 상품 기능 상품 등록 주문 기능 상품 주문 UML Spring Event를 사용한 이유 어플리케이션을 개발하고 운영하다보면 다양한 추가기능이 생기고 수정사항이 생깁니다. 주문 기능을 생각해봅시다. 처음에는 정말 주문기능 하나만 가지고 개발이 되었더라도 서비스가 발전하면서.. 2023. 9. 1. Spring - Pageable 최대 페이지 크기 제한 0. 들어가며 Spring MVC에서 페이징 기능을 구현할 때 Pageable을 통해서 많이 구현합니다. Pageable은 Spring에서 페이징 기능에서 자주 사용하는 기능들을 정의해 놓은 인터페이스입니다. 클라이언트에서 어떤 리소스의 요청결과값이 굉장히 많은 경우, 전체 데이터를 한 번에 반환하는 것이 아니라 전체 개수를 일정한 크기의 Page로 나누고 Page의 번호로 Page를 구분하는 형태로 구현되어 있습니다. 페이징 API를 구현할 때, 컨트롤러에서 Pageable 타입으로 파라미터를 전달받아서 넘기면 Spring Data JPA를 사용한다면, 따로 다른 객체로 변환해 줄 필요 없이 바로 사용할 수도 있고 여러 가지 장점이 많습니다. 그래서 페이징 기능을 구현할 때 Pageable을 많이 사용.. 2023. 8. 26. @ModelAttribute 어노테이션을 생략했을 때 파라미터가 바인딩되는 과정 들어가며 Spring MVC 구조에서 컨트롤러 코드를 작성할 때, 클라이언트에서 넘어온 정보를 DTO 클래스를 만들어서 바인딩하는 경우가 많습니다. 이렇게 구현하면 파라미터가 많은 경우 하나의 클래스에 모아서 관리하기 편하고, 비즈니스 로직을 처리할 서비스 계층에서도 다루기 편하기 때문에 많이 사용됩니다. 코드로 작성하면 아마 다음과 비슷한 구조겠죠. @GetMapping("/api/v1/admin/users") public ResponseEntity list(UserSearchRequest userSearch, Pageable pageable) { Page result = userViewService.findAll(userSearch, pageable); List responseContent = res.. 2023. 8. 25. SpringBoot JSON 형태의 날짜타입 LocalDateTime 으로 받기 오늘은 기억보단 기록을 블로그를 참조하여 공부한(이라 쓰고 '따라한'으로 읽는) 내용을 정리하려고 합니다. 작성한 코드는 모두 Github 에 있습니다. 0. 시작하며 Spring을 사용해서 API 서버 혹은 웹 프로젝트를 개발하면서 Controller에서 요청을 받거나 응답을 주는 DTO에서 날짜 혹은 시간과 관련된 정보를 String 으로 선언한 필드로 받아서 LocalDateTime으로 변환하는 것을 많이 보았고, 얼마 전까지 저 또한 그렇게 처리했습니다. 그렇게 변환하면서도 비효율적이라고 많이 생각하고 고민하며 찾아보다가 좋은 방법을 찾아서 공유하려고 합니다. 저는 다음과 같은 개발환경에서 진행하였습니다. - SpringBoot 2.7.5 - Java 11 - Gradle7 - spring-boo.. 2022. 11. 17. @Configuration 1. 특징 스프링 3.X 이상의 프레임워크에서는 XML 파일에서 하는 Bean의 정의를 자바클래스로서 선언할수 있게 한다. Spring IoC 컨테이너에게 설정 정보(Meta Data)임을 알려줌 XML 파일에서 아래와 같이 설정하는 것과 동일한 역할을 수행( 클래스를 스프링 Bean으로 등록하고 이미 등록된 bean들에 대해 어노테이션을 활성화하는 것) 개발자가 직접 제어할 수 없는 외부 라이브러리 혹은 설정을 위한 클래스를 Bean으로 등록할 때 @Bean 어노테이션과 함께 사용되기도 함. (단독으로도 사용 가능) @Bean 단독 사용 시, bean 등록이 되긴 하지만 IoC 컨테이너에서 싱글톤 객체로 생성되지 않음 @Target(ElementType.TYPE) @Retention(RetentionP.. 2021. 1. 10. DI(Dependency Injection) 애플리케이션 코드를 작성할 때, 애플리케이션에 특정한 기능이 필요하다면 외부 라이브러리를 호출하여 사용하곤합니다. 개발자가 프로그램의 흐름의 주도권을 가지고 제어하는 구조입니다. 하지만, 스프링과 같은 프레임워크에서의 개발은 프레임워크에서 필요할 때 애플리케이션 코드를 호출하는 형태로 동작하므로 프레임워크가 흐름의 주체가 됩니다. 이렇게 제어권이 개발자에게서 프레임워크로 흐름이 바뀌었다고 하여 IoC(Inversion of Control : 제어의 역전)이라고 부릅니다. 이 때, 프레임워크에서 제어권을 가지는 것이 컨테이너(Container)입니다. 컨테이너는 객체의 생성과 생명주기 관리(Life Cycle) 관리등을 도맡아서 하게됩니다. 출처 : nextree.co.kr/p11247/ 세 가지 DI 컨.. 2021. 1. 3. 이전 1 2 다음