Spring log4j2 적용기

log4j vs logback vs log4j2 를 비교 해보고 log4j2를 사용해보기로 결정했다. Spring Framwork에 log4j2를 적용한 과정을 정리해본다. 의존 중복 처음에 log4j2 의존을 아래와 같이 추가해서 실행하니 에러가 발생했다. SLF4J가 여러 개 바인딩 되어서 발생한 문제였다. implementation 'org.springframework.boot:spring-boot-starter-log4j2:2.6.3' Spring Boot에 로깅 모듈을 제외 시켜서 해결할 수 있다. implementation('org.springframework.boot:spring-boot-starter-data-jpa:2.6.2') { exclude module: "spring-boot-starter-logging" } 멀티 프로필 Spring Boot에서는 Logback처럼 프로필 별 xml 자동 감지가 안된다. properties 파일을 통해서 사용할 로깅 xml파일을 지정해줘야 된다....

2025-02-01 · 1 min · 184 words

@RequestMapping같이 url을 파싱할 수 있는가

PathMathcer 또는 AntPathMatcher 를 사용하면 된다. 참고 자료 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/AntPathMatcher.html

2024-09-15 · 1 min · 9 words

@Profile, @ActiveProfile

profile 설정에 따라 다른 Bean을 사용하고 싶다면 @Profile을 사용할 수 있다. profile 설정에 따라 테스트를 끄고 켜고싶다면 @ActiveProfile을 사용할 수 있다. 참고 자료 http://wonwoo.ml/index.php/post/1933

2024-09-15 · 1 min · 24 words

@Async 사용하기

목표 @Async을 사용하는 이유를 이해한다. @Async의 사용 방법을 이해한다. @Async란? bean의 메소드에 @Async를 붙이면 별도의 스레드로 메소드가 실행된다. 호출한 쪽에서는 메소드 호출이 완료되기까지 기다리지 않는다. @Async 사용 방법 configuration @Async를 사용하기 위해서는 configuration에 @EnableAsync 를 추가해야된다. @EnableAsync @Configuration class AsyncConfig @EnableAsync의 옵션 annotation: 기본값으로는 @Async를 사용하지만 커스텀 애노테이션을 사요하고 싶을 때 사용할 수 있따. mode: advice의 종류를 나타낸다. PROXY와 AspectJ가 있다. proxyTargetClass: 프록시 모드를 사용할 때만 사용된다. CGLIB과 JDK가 있다. order: AsyncAnnotationBeanPostProcessor가 적용될 순서를 설정한다....

2024-09-15 · 2 min · 344 words

특정 주기마다 실행되는 메서드

Spring task라는 내장된 기능 통해 특정 메서드를 주기적으로 실행하는 것이 가능하다. 스케쥴링 지원 활성화 Configuration에 @EnableScheduling 어노테이션을 추가하면 활성화된다. @Configuration @EnableScheduling public class SpringConfig { ... } fixed 방식 fixed 방식에는 2가지가 있다. fixedDelay: 작업이 종료된 시간부터 지정된(ms단위) 시간 뒤에 재실행. fixedRate: 작업이 시작된 시간부터 지정된(ms단위) 시간 뒤에 재실행. @Scheduled(fixedDelay = 1000) public void scheduleFixedDelayTask() { System.out.println( "Fixed delay task - " + System.currentTimeMillis() / 1000); } @Scheduled(fixedRate = 1000) public void scheduleFixedRateTask() { System....

2024-09-15 · 1 min · 181 words

통합 테스트에 @Transactional을 붙이면 안되는 이유

배경 통합 테스트중에 DB에 추가된 데이터를 제거하기 위해서 @Transactional을 사용하는 경우가 있다. 이럴 경우 버그가 있어 실패해야될 테스트가 통과되어버리는 문제가 발생할 수 있다. @SpringBootTest @Transactional internal class CartItemsControllerTests { ... @Test fun getAllCartItems() { val cart = Cart() cart.addProduct(product, 3) cartsRepository.save(cart) mockMvc.perform(get("/carts/{id}/items", cart.id)) .andExpect(status().isOk) .andExpect(jsonPath("$.[*].id").value(hasItem(cart.items[0].id.toString()))) .andExpect(jsonPath("$.[*].product.id").value(hasItem(product.id.toString()))) .andExpect(jsonPath("$.[*].product.name").value(hasItem(product.name))) .andExpect(jsonPath("$.[*].quantity").value(3)) } } 이유 서비스에 @Transactional이 붙어있지 않아서 실패되어야할 요청이 통과되어버린다. lazy loading이 동작하지 않아서 실패해야 되는 경우에도 통과 되어버린다. 변경 탐지가 동작하지 않아서 실패해야 되는 경우에도 통과 되어버린다....

2024-09-15 · 1 min · 107 words

이미 등록된 빈에 추가 설정 하는 법

배경 테스트 환경에서 컨테이너에 등록된 빈을 대상으로 추가 설정하는 방법이 필요했다. @PostConstruct JSR-250 스펙으로 있는 애노테이션이다. ApplicationContext에 등록된 객체 중에 해당 애노테이션이 붙어있는 메소드가 있다면, 해당 빈이 생성되고 난 뒤에 메서드를 실행한다. 따라서, 아래와 같이 설정할 수 있다. @TestConfiguration class TestConfig { @Autowired private SomeBean someBean; @PostConstruct private void initSomeBean() { // someBean.setProperty("qwe"); } } 참고 자료 https://stackoverflow.com/questions/57920642/spring-java-config-configure-already-existing-bean https://docs.spring.io/spring-framework/docs/current/reference/html/core.html https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-postconstruct-and-predestroy-annotations

2024-09-15 · 1 min · 60 words

빈 등록시 @Component가 아닌 @Configuration을 사용하는 이유

@Configuration 안에 @Component가 있다. 즉 둘 다 클래스 자체가 빈으로 등록된다. 내부에서 선언한 빈을 싱글톤으로 등록하고자 하는 경우에는 @Configuration이 붙어야 된다. 큰 차이점은 @Configuration은 CGLIB wrapper를 사용하여 모든 빈 메서드가 자신이 현재 클래스의 첫 호출처럼 동작한다. 따라서 아래의 코드는 @Component는 동작을 하지 않는다. CGLIB은 프록시 빈 객체를 만들어서 실제로 사용될 때 객체가 생성되기 때문에 빈에 다른 빈을 의존할 수 있다. @Configuration public static class Config { @Bean public SimpleBean simpleBean() { return new SimpleBean(); } @Bean public SimpleBeanConsumer simpleBeanConsumer() { return new SimpleBeanConsumer(simpleBean()); } }

2024-09-15 · 1 min · 85 words

XML 빈 등록 vs 어노테이션 빈 등록

XML 장점: 애플리케이션을 구성하는 빈과 의존관계, 설정 등을 통제하고 관리하기 쉽다. 단점: XML 문서를 관리하기 때문에 개발 속도가 느려진다. 어노테이션 장점: 복잡한 XML 문서 생성과 관리가 필요없이 개발속도를 향상 시킬 수 있다. 단점: XML처럼 상세한 메타정보 항목을 지정할 수 없고, 클래스당 한 개 이상의 빈을 등록할 수 없다.

2024-09-15 · 1 min · 48 words

WebClient로 URL parameter 보내기

목표 Spring 에서 제공하는 WebClient로 HTTP 요청을 보낼 때, URL parameter를 전송하는 방법을 알아본다. parameter 보내기 webClient.get() .uri(uriBuilder - > uriBuilder .path("/products/") .queryParam("name", "{name}") .build("asdf+asdf")) .retrieve() .bodyToMono(String.class) .onErrorResume(e -> Mono.empty()) .block(); 위와 같이 작성하면 /products?name=asdf%2asdf 로 요청이 보내지는 것을 확인할 수 있다. 주의점 아래와 같이 쿼리 파라미터를 넘기면 예상치 못한 방식으로 URL 인코딩이 될 수 있기 때문에 주의해야된다. 아래와 같이 요청을 보내면 ‘+’ 문자가 URL 인코딩 되지 않고 요청이 보내진다. /products%3Fname=asdf+asdf 반대로 ‘?...

2024-09-15 · 1 min · 168 words

Type을 만족하는 모든 Bean 주입하기

생성자나 setter에 List 를 파라미터로 두면 된다. public Class Xyz { private List<Daemon> daemons; @Autowired public void setDaemons(List<Daemon> daemons){ this.daemons = daemons; } }

2024-09-15 · 1 min · 24 words

TransactionTemplate 이용한 트랜잭션 관리

@Transactional 어노테이션을 사용하지 않고, 트랜잭션을 직접 관리하고 싶은 경우가 있었다. 이때 TransactionTemplate를 사용하면 된다. 트랜잭션 외부에 리턴을 해야되는 경우 return transactionTemplate.execute(new TransactionCallback() { // the code in this method runs in a transactional context public Object doInTransaction(TransactionStatus status) { updateOperation1(); return resultOfUpdateOperation2(); } }); 트랜잭션 외부에 리턴이 필요없을 경우 transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { updateOperation1(); updateOperation2(); } }); 참고 자료 https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#tx-prog-template

2024-09-15 · 1 min · 64 words

Spring 이벤트 처리

도메인 간의 복잡한 의존성을 제거하기 위해서 Spring의 이벤트를 이용할 수 있다. 이벤트를 사용하기 위해서는 3가지를 사용해야된다. 참고로, Spring Framework 4.2부터 지원하는 어노테이션 방법을 다룬다. 이벤트 클래스 이벤트 퍼블리셔 이벤트 리스너 이벤트 클래스 이벤트에 데이터를 저장하기 위한 클래스로 자유롭게 클래스를 선언하면 된다. public class MenuRegisteredEvent { private final Menu menu; public MenuRegisteredEvent(final Menu menu) { this.menu = menu; } public Menu getMenu() { return menu; } public Long getMenuGroupId() { return menu....

2024-09-15 · 2 min · 236 words

Spring 실행 시 포트 번호 지정 방법

java -jar -Dserver.port=8083 spring-5.jar 또는 java -jar spring-5.jar --server.port=8083 참고 자료 https://recordsoflife.tistory.com/325

2024-09-15 · 1 min · 12 words

Spring Framework에서 멀티 모듈 사용해보기

이 글은 Spring Framework에서 멀티 모듈을 적용하면서 겪은 트러블 슈팅들을 정리한 글이다. 모듈 및 패키지 구조 크게 api, client, core라는 모듈로 나뉘어지고, api와 client는 core 모듈의 의존한 상태다. 이후 소개할 트러블 슈팅들은 api와 core 사이의 관계로 설명하겠다. api 모듈과 core 모듈은 아래의 디렉터리 구조를 가지고 있다. 아래는 main 메서드가 있는 클래스의 코드다. @SpringBootApplication public class HyNoticeApplication { public static void main(String[] args) { SpringApplication.run(HyNoticeApplication.class); } } 트러블 슈팅 Parameter 0 of constructor in hynotice....

2024-09-15 · 1 min · 208 words

Spring Custom Conditions

배경 config 클래스 중에 Condition 인터페이스의 구현체가 있었는데, 어떤 용도인지 이해하지 못했다. Custom Conditions 정의 조건부로 빈을 등록할 때 @Conditional 애노테이션을 사용할 수 있다. 이 애노테이션에서 사용할 조건을 클래스로 만들 수 있다. class Java8Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return JavaVersion.getJavaVersion().equals(JavaVersion.EIGHT); } } 사용 예 @Service @Conditional(Java8Condition.class) public class Java8DependedService { // ... } 참고 자료 https://www.baeldung.com/spring-conditional-annotations

2024-09-15 · 1 min · 63 words

PropertySourcesPlaceholderConfigurer

배경 Spring Boot의 자동-구성을 사용하지 않으니 @Value("\${...}") 어노테이션으로 property가 가져와지지 않았다. 원인 PropertySourcesPlaceholderConfigurer: bean 정의 프로퍼티 값이나 @Value를 Spring 내 Environment와 PropertySource의 집합으로 처리해주는 클래스이다. Spring Boot로 실행시에는 자동-구성으로 bean으로 등록된다. Environment: 현재 실행 중인 Spring 애플리케이션의 환경을 나타내는 인터페이스. 가지고 있는 데이터로 profile과 properties로 나눌 수 있다. profile: 특정 프로필이 활성화 된 경우에만 bean이 등록되도록 사용할 수 있다. properties: properties 파일, JVM 시스템 properties, 시스템 환경 변수 등을 출처로 가져온다....

2024-09-15 · 1 min · 174 words

properties에 비밀 번호 남는 문제 해결

현재는 일단 properties에 비밀번호를 입력하지 않고 실행시 아래와 같이 실행하도록 구현해뒀다 java -jar -Dspring.datasource.password=abcd1234 abc.jar 환경 변수를 이용하는 방법도 있다. https://stackoverflow.com/questions/37404703/spring-boot-how-to-hide-passwords-in-properties-file

2024-09-15 · 1 min · 21 words

OncePerRequestFilter

배경 팀 코드에 OpenPerRequestFilter를 상속한 형태의 Filter가 존재했다. 이 클래스는 어떤 역할인지 확인할 필요가 있었다. 필요한 상황 Filter는 서블릿 실행 전과 후에 호출된다. 요청이 서블릿으로 들어오면 서블릿은 다른 서블릿으로 포워딩 할 수도 있다. 이 과정에서 같은 필터를 여러 번 호출할 수도 있다. Spring은 이런 상황에서 필터가 한번만 호출되는 것을 보장시켜주기 위해 OncePerRequestFilter을 제공한다. 사용법 OncePerRequestFilter를 상속한 클래스를 정의하고, doFilterINternal() 메소드를 override하면 된다. public class AuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String usrName = request....

2024-09-15 · 1 min · 99 words

Kotlin과 사용시 open 해야되는 문제

배경 스프링은 트랜잭션 등의 AOP를 지원하기 위해 CGLIB을 사용하여 프록시를 만들기 위해, 클래스들을 동적으로 상속한다. 따라서, final 클래스는 컴포넌트로 사용할 수 없다. Kotlin 클래스는 기본값이 final 이므로 매번 open 키워드를 붙여줘야되는 번거로움이 있다. kotlin-maven-allopen 이를 해결해주기 위해 kotlin에서는 kotlin-maven-allopen이라는 플러그인을 제공해준다. @Configuration이나 @Transactional, @Component 등 스프링 관련 어노테이션이 붙어있는 클래스나 메서드는 자동으로 open 시켜서 CGLIB에 사용할 수 있게 해준다. <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <configuration> <compilerPlugins> <plugin>spring</plugin> </compilerPlugins> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-allopen</artifactId> <version>${kotlin....

2024-09-15 · 1 min · 79 words