공부/Spring
[Spring] ReactiveMongoTemplate vs ReactiveMongoRepository
ReactiveMongoTemplate과 ReactiveMongoRepository는 반응형 MongoDB 작업을 수행하는 두 가지 주요 방식이다. ReactiveMongoRepository를 사용해야 하는 경우ReactiveMongoRepository는 주로 기본적인 CRUD 작업을 간편하게 처리할 때 유용하다.단순한 조회, 저장, 삭제 등의 작업이 자주 필요할 때는 repository가 더 직관적이고, 필요한 메서드들이 미리 정의되어 있어 코드가 간결해진다. 단순한 CRUD 작업: 기본적인 조회(findById, findAll), 저장(save), 삭제(deleteById) 등의 작업메서드 이름을 통한 쿼리 정의: findByName, findByStatus 등 메서드 이름만으로 간단한 조건 기반 조..
[Spring] MongoDB 조회 - Stream, Aggregation 비교
Spring에서 몽고디비를 사용할 때스트리밍 조회(Stream Processing)와 MongoDB Aggregation 중 어떤 방법이 더 좋은지 데이터의 특성과 사용 목적을 고려해야 한다. 스트리밍 조회 (Stream Processing)장점메모리 효율성: 전체 데이터를 한 번에 메모리에 로드하지 않고, 하나씩 처리하기 때문에 메모리 부담이 적다.단순한 로직: 데이터 하나하나를 순차적으로 처리하는 데 적합하여, 복잡한 집계나 가공 작업을 서버 측 코드에서 쉽게 처리할 수 있다.단점네트워크 부담: 모든 데이터를 서버로 전송해야 하므로 네트워크 트래픽이 높아질 수 있다.속도 저하 가능성: MongoDB 내에서 바로 처리하지 않고, 애플리케이션 서버에서 작업을 수행해야 하므로 처리 속도가 느려질 수 있..
[Spring] 스프링 AOP 포인트컷
포인트컷 지시자 AspectJ 는 포인트컷을 편리하게 표현하기 위해 특별한 표현식을 사용한다. 포인트컷 표현식은 AspectJ가 제공하는 포인트컷 표현식을 줄여서 말하는 것으로execution 같은 포인트컷 지시자(Pointcut Designator, PCD)로 시작한다. 지시자 종류 execution : 메소드 실행 조인 포인트를 매칭한다. 스프링 AOP 에서 가장 많이 사용하고 기능도 복잡하다. within : 특정 타입 내의 조인 포인트를 매칭한다.args : 인자가 주어진 타입의 인스턴스인 조인 포인트this : 스프링 AOP 프록시를 대상으로 하는 포인트target : 스프링 AOP 프록시가 가리키는 실제 대상으로 하는 조인 포인트@target : 실행 객체의 클래스에 주어진 타입의 어노테이션..
[Spring] Spring AOP 구현 예제
라이브러리 추가build.gradle 에 의존성 추가를 해준다. implementation 'org.springframework.boot:spring-boot-starter-aop'위의 라이브러리 추가로 aspectJ 관련 라이브러리를 등록하고 스프링 부트가 AOP 관련 클래스를 자동으로 스프링 빈에 등록해준다. @Aspect 사용 예제스프링은 @Aspect 어노테이션으로 편리하게 포인트컷과 어드바이스로 구성되어 있는 어드바이저 생성 기능을 지원하며 어드바이저로 사용할 클래스에 @Aspect 어노테이션을 붙여줌으로써 스프링 AOP 를 적용할 수 있다. 주의할 점으로 스플이 AOP 적용시에는 private, final 메소드는 AOP 적용이 불가능하다. @Slf4j@Aspectpublic class As..
[Spring] AOP 개념 및 용어 정리
AOP란Aspect-Oriented Programming , 관점 지향 프로그래밍이란 뜻으로 어떤 로직을 핵심적인 관점과 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하는 것이다. 부가 기능과 부가 기능을 어디에 적용할 지 선택하는 기능을 합해서 하나의 모듈로 만든 것을 Aspect라고 한다. 이 Aspect 를 사용한 프로그래밍 방식을 AOP 라고 한다. AOP는 OOP를 대체하기 위한 것이 아닌 횡단 관심사(하나의 부가 기능이 여러 곳에 동일하게 사용됨)를 깔끔하게 처리하기 어려운 OOP의 부족한 부분을 보조하는 목적으로 개발되었다. AOP 의 대표적인 구현으로는 AspectJ 프레임워크가 있다. AOP 적용 방식적용 방식에는 크게 3가지 방식이 있다. 컴파일 시점클래스 로딩 시..
[Spring] @Aspect란, 생성 과정 설명
@Aspect란 AOP(관점 지향 프로그래밍)를 가능하게 하는 AspectJ 프로젝트에서 제공하는 어노테이션이다. @Aspect를 스프링 프록시에 적용하려면 어드바이저(Advisor)를 만들어서 스프링 빈으로 등록하면 된다. 그러면 자동 프록시 생성기는 스프링 빈으로 등록된 어드바이저들을 찾고 스프링 빈에 자동으로 프록시를 적용해준다. @Aspect 프록시 예제 빨간 박스는 포인트컷 부분이고 초록색 박스는 어드바이스 부분이다. @Aspect를 어드바이저로 변환해서 저장하는 과정 1. 실행 : 스프링 어플리케이션 로딩 시점에 자동 프록시 생성기를 호출한다. 2. 모든 @Aspect 빈 조회 : 자동 프록시 생성기는 @Aspect 어노테이션이 붙은 스프링 빈을 모두 조회한다. 3. 어드바이저 생성 :..
[Spring] 빈 후처리기
이전에 작성했던 프록시 팩토리의 문제점을 해결하기 위해서 빈 후처리기를 사용한다고 했다. 프록시 팩토리 내용에 대해 알고싶으면 아래 링크를 참고하면 된다. https://bsssss.tistory.com/1482 빈 후처리기란 일반적으로 @Bean 이나 @Component 를 사용하면 스프링은 대상 객체를 생성하고스프링 컨테이너 내부의 빈 저장소에 등록한다. 빈 후처리기는 객체를 조작할 수도 있고, 다른 객체로 바꿔치기 하는 것도 가능하다. 빈 후처리기 - 스프링 빈 등록 과정생성 : 스프링 빈 대상이 되는 객체를 생성(@Bean, 컴포넌트 스캔 포함)전달 : 생성된 객체를 빈 저장소에 등록하기 직전에 빈 후처리기에 전달후 처리 작업 : 빈 후처리기는 전달된 스프링 빈 객체를 조작하거나 다른 객체로 ..
[Gradle] Gradlew 빌드 시 gradle 다운로드 속도가 느릴 때
이미지 빌드 중 ./gradlew 실행을 위해 gradle 다운로드하는데 시간이 너무 오래걸리는 문제가 있었다. 빠를때도 있고 느릴때도 있었는데 계속 기다릴 수 없기에... 해결해보는걸로 하자. 찾아보니 종종 배포파일 다운로드가 느리다는 것 같았다. 해결 방법으로는 다운로드 받는 gradle 주소를 변경해서 진행하면 된다. 파일 위치는 gradle/wrapper/gradle-wrapper.properties 에 있고 distributionUrl 에 있는 주소를 변경해주면 된다. Downloading https://services.gradle.org/distributions/gradle-[버전]-bin.zip Downloading https://downloads.gradle.org/distributions..
[Spring] Thread Pool - pool size설정
Thread Pool Thread Pool 은 여러 개의 쓰레드를 유지하고 관리하기 위해 사용된다. Thread Pool 의 사이즈 쓰레드를 불필요하게 많이 만들게 되면 메모리의 낭비가 심해지고 너무 적은 수의 쓰레드를 만들게 되면 효율성이 떨어진다. 쓰레드의 개수를 고정 시키는 것보다 서비스가 실행되는 CPU의 코어 개수에 따라 유동적으로 생성할 수 있도록 해주는 것이 좋다. 많이 생성하는 것이 아니라 어떤 작업을 처리하느냐에 따라 기준이 바뀔 수 있다. CPU 처리가 많은 경우 - CPU 코어가 N개인 경우 N+1만큼의 쓰레드를 생성해주면 최적에 가까운 성능을 낼 수 있다고도 한다. I/O 작업이 많은 경우 - N*2 만큼의 쓰레드를 생성해준다.
[Querydsl] Resolved [com.querydsl.core.types.ExpressionException ~ ]
selet 문에 내가 원하는 값으로 리턴하기 위해 Querydsl 에서 Projections.fileds를 사용하는데 다음과 같은 에러가 발생했었다. @Override public List getMasterIdList(Long memberId) { return jpaQueryFactory.select( Projections.fields(AnswerDTO.class, answer.answerId.as("answerId"), answer.answerId.count().coalesce(0L).as("answerCount")) ) .from(answer) .where(answer.mberId.eq(memberId)) .fetch(); } Projections의 경우 생성자 기반이 아닌 필드 기반으로 가져올 때 ..