728x90

Backend/Spring+Boot 64

의존성 주입시 중복되는 타입에 대한 처리

특정 클래스의 의존성을 주입하려고 할 때 동일한 타입이 여러개 존재하는 경우가 있을 수 있다. 하나의 Interface 를 다수의 클래스에서 implements 해서 다형성을 구현한 경우가 바로 그것인데 @Autowired 를 통한 의존성 주입이나 생성자를 통한 의존성 주입 모두 타입을 기준으로 하기 때문에 이 경우 적절한 Bean을 결정하지 못해 의존성 주입이 실패한다. 이 때는 일반적으로 @Qualifier 어노테이션을 통해 Bean id 를 명시해주면 해당 의존성이 정상적으로 주입된다. 하지만 이것 말고도 의존성을 주입하려는 클래스 변수의 명칭을 Bean id로 만들면 @Qualifier 어노테이션을 명시한 것과 동일한 효과를 볼 수 있다. 뭔가 더 간단하고 쉬운 방법인 것 같지만 서칭을 해보니 이..

Backend/Spring+Boot 2021.07.23

Spring에서 권장되는 의존성 주입 방법

A클래스에서 B클래스의 메소드를 사용하려면 A클래스에서 B클래스를 인스턴스화 해서 사용해야 한다. 이 때 B를 A의 의존성이라고 하고 B의 인스턴스를 생성하는 것을 의존성을 주입한다고 표현한다. 이러한 연결을 위해 일반적으로 A클래스에서 코드상 new B() 를 통해 B의 의존성을 직접 주입해야 하지만 Spring 환경이라면 이러한 의존성성 주입을 Spring에서 담당해준다. 하지만 컨테이너에게 의존성을 주입해 달라는 액션을 취해야 하는데 그 방법은 아래와 같이 세 가지가 있다. 생성자 정의 Setter 메소드 정의 필드에 @Autowired 지정 이 중 권장되는 방식은 생성자 정의 방식이다. 여러 이유가 있겠지만 개인적으로 많이 공감했던 내용 위주로 정리해본다. Setter 메소드 정의 방식의 경우 기..

Backend/Spring+Boot 2021.07.23

RestClient 구성시 고려사항

서버to서버 통신을 할 경우 RestClient 라이브러리를 통해 로직을 구현하곤 한다. 많이들 사용되는 것이 RestTemplate, Feign 등 인데 과거에는 그냥 기본값으로 사용했는데 MSA 환경을 고려하다보니 이것저것 추가로 고민을 하게 됐고 그 결과를 기록한다. 다만 WebClient의 경우 동작방식이 조금 다르기 때문에 여기에서 고려대상은 아니다. 1. RestClient 는 host 별로 생성해야 할까? 서버마다 타임아웃이나 default 헤더가 다를 수 있기 때문에 각각 구성하는 것이 맞다고 본다. 물론 하나의 RestClient로 하더라도 그 안에서 로직을 분기처리할 수 있지만 많은 서버와 통신해야 하는 MSA 구성의 특징을 생각하면 하나의 RestClient 에 들어가야할 분기로직이 ..

Backend/Spring+Boot 2021.07.20

UriComponentsBuilder

URL 에는 사용할 수 있는 문자가 제한되어 있기 때문에 한글과 일부 특수문자, 공백 등의 문자들이 포함될 경우 반드시 인코딩을 해줘야 한다. 일반적으로 RestTemplate 나 브라우저 같은 클라이언트 통할 경우 자동으로 인코딩을 해주지만 몇몇 클라이언트에서는 인코딩을 해주지 않기 때문에 그때는 우리가 URL을 만들 때 인코딩을 미리 해줘야 한다. POST 방식이라면 Content-Type 헤더에 charset를 직접 명시하던지 HttpServletRequest.setCharacterEncoding() 로 문자셋을 지정해주면 되고 GET 방식이라면 가장 기본적으로 아래와 같은 방법을 사용할 수 있다. StringBuilder uri = new StringBuilder("http://localhost:..

Backend/Spring+Boot 2021.07.19

@RunWith(SpringRunner.class)

SpringBoot 2.1 이전 버전을 사용할 경우 테스트 클래스는 아래와 같이 정의했을 것이다. @RunWith(SpringRunner.class) @SpringBootTest public class Test{ ... } 그런데 SpringBoot 2.1 부터는 @RunWith(SpringRunner.class) 이 없어도 테스트 코드가 잘 동작한다. 그냥 기계적으로 복붙해서 사용했었는데 왜 그런지 궁금해져서 찾아봤다. 일단 @RunWith 어노테이션은 테스트 실행방법을 확장할 때 사용하는 어노테이션으로 @RunWith(SpringRunner.class) 라고 정의하면 JUnit4.x 프레임워크가 내장된 Runner를 실행할 때 SpringRunner.class라는 확장된 클래스를 실행하게 된다. Sp..

Backend/Spring+Boot 2021.07.13

@Async 설정

Spring 환경에서는 @Async 어노테이션으로 간단한게 논블로킹 로직을 구현할 수 있다. 결국 스레드 풀을 사용하는 것인데 기본 설정으로 사용하면 풀 사이즈는 1로 고정되어 1개만 동시실행이 가능하고 나머지 요청은 무한대로 큐에 쌓여서 대기하게 된다. @Async 자체가 논블로킹을 지원하기 때문에 큐에만 쌓고 대기 바로 작업을 종료하지만 우리가 원하는 동작은 아니다. 스레드 풀 사용하는 경우 대부분 일정수치 이상 동시처리가 진행되길 원한다. 이것 말고도 경우에 따라 반드시 지정해야할 논블로킹 로직의 설정이 필요하기 때문에 일반적으로 아래와 같이 스레드풀을 커스텀하게 정의해서 사용한다. @Bean public Executor defaultAsyncExecutor() { ThreadPoolTaskExec..

Backend/Spring+Boot 2021.07.13

CircuitBreaker, Resilience4j, RestClient

CircuitBreaker 회로차단기를 뜻으로 (금융·주식 파동에 대비한) 거래 일시 중지 (조치), 안전 장치. 라는 뜻도 가지고 있다. 프로그래밍에서도 비슷한 의미로 사용되며 API를 통한 외부 서비스와의 통신이 많은 MSA 환경에서 반드시 필요한 개념이다. 예를 들어 A서비스에서 B서비스의 API를 사용하고 있는데 B서비스에서 장애가 발생했다고 가정해보자. 장애에는 여러가지 상황이 있을 수 있는데 대표적으로 서비스가 아예 죽었거나 갑자기 트래픽이 몰려 처리 시간이 오래 걸리는 경우를 생각해볼 수 있다. 타겟 서비스가 아예 죽어있는 상황이라면 그나마 나은 편에 속한다. 일반적으로 호출하는 서비스에서는 이러한 상황에 대해 예외처리를 해놓았을 것이기 때문이다. 별도의 공통 에러 페이지를 띄우는 것이 바로..

Backend/Spring+Boot 2021.07.09

ObjectMapper json 직렬화/역직렬화 주의사항

1. 직렬화를 위해서는 각 인스턴스 변수에 대한 Getter 메소드가 포함되어 있거나 각 인스턴스 변수에 @JsonProperty 가 명시되어 있어야 한다. 이는 택1로 적용하면 된다. 2. 역직렬화를 위해서는 기본생성자가 반드시 필요하다. 각 인스턴스 변수에 대한 Setter 메소드가 필수로 필요하진 않지만 존재한다면 그것을 활용한다. 3. 일반적으로 ObjectMapper 는 기본으로 쓰지 않고 아래와 같이 재정의해서 프로젝트에서 static 메소드로 사용한다. public class ObjectMapperUtils { private static final ObjectMapper mapper = new ObjectMapper(); static { mapper.registerModule(new Java..

Backend/Spring+Boot 2021.07.07

@RequestMapping consumes, produces

@ReqeustMapping 정의시 아래와 같이 consumes와 produces 를 정의할 수 있다. @RequestMapping("/test" , consumes = MediaType.APPLICATION_JSON_UTF8_VALUE , produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public String hello(){ return "hello"; } consumes 는 클라이언트로부터 수신하고자 하는 데이터 포맷을 지정하는 것이고 produces는 서버에서 응답하고자 하는 데이터 포맷을 지정하는 것이다. 클라이언트 입장에서는 서버쪽 api 호출시 보낼 데이터의 포맷을 Content-Type 이라는 헤더값으로 명시하고 응답받을 수 있는 데이터 포맷을 Ac..

Backend/Spring+Boot 2021.07.07

SpringBoot Redis Cluster Lettuce 설정

공식 홈페이지에 Redis Cluster 기준 client 설정이 있긴한데 Jedis 기반이라 Lettuce 설정을 기록해둔다. 1. application.yml 설정 참고로 구조는 꼭 아래와 같이 할필요는 없다. 그냥 본인이 편한대로 하면 된다. config 클래스에서 그대로 불러오기만 하면 된다. spring: redis: cluster: nodes: localhost:6370,localhost:6371,localhost:6372 2. Config 설정 @Configuration //@EnableRedisRepositories//없어도 잘 돌아가는듯? 스프링부트 자동설정에 포함되어 있음. public class RedisConfig { //@Value("${spring.redis.host}") //p..

Backend/Spring+Boot 2021.05.04
728x90