728x90

Backend 150

SpringBoot 1.5.x 에서 Junit5 사용하기 (with Maven)

1. 사용할 junit-jupiter, junit-platform 버전 properties 로 지정 - 이건 필수는 아니다. 그냥 버전을 전역적으로 관리하기 위해... 5.7.1 2. pom.xml 에서 SpringBoot 1.5.x 에 포함된 Junit4 의존성 제외처리 org.springframework.boot spring-boot-starter-test test junit junit 3. junit-jupiter-api, junit-jupiter-engine 의존성 추가 org.junit.jupiter junit-jupiter-api ${junit-jupiter.version} test org.junit.jupiter junit-jupiter-engine ${junit-jupiter.version..

Backend/TDD, Junit 2021.07.20

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

한글 인코딩과 new String, getBytes

http 통신에서 한글을 사용한다면 인코딩은 필수이다. 기본적으로 일부 한글과 특수문자, 공백 등의 문자들은 그대로 http 프로토콜에 포함될 수 없고 별도로 인코딩을 해서 보내야 한다. 일반적으로 인터넷 브라우저나 코드상에서 사용하는 RestTemplate 같은 RestClient 에서는 이러한 인코딩을 자동으로 해준다. 인코딩된 데이터를 받는 쪽에서는 역시 디코딩이 필요하다. 이는 일종의 통신규약으로 인코딩과 디코딩의 기준이 되는 문자셋(ISO-8859-1, EUC-KR, UTF-8)은 서로 동일해야 하고 한글을 사용한다면 EUC-KR 또는 UTF-8을 문자셋으로 선택해야 한다. 참고로 ISO-8859-1는 알파벳과 일부 특수기호만을 처리할 수 있고 한글은 처리할 수 없다. 결국 시작은 인코딩인데 P..

@Async, CompletableFuture, parallelStream

논블로킹, 비동기, 병렬 과 관련되어 있을 때 자주 거론되는 것들이다. 비슷한거 같으면서도 다른 이 세가지 개념에 대해 정리한다. 우선 논블로킹, 비동기 은 병렬처리를 위한 과정이라고 생각하면 된다. 병렬은 동시에 여러가지 작업이 수행되는 것이고 이를 위해 어플리케이션 입장에서는 일을 시키는 과정이 논블로킹으로 진행되어야 한다. 또한 논블로킹으로 수행된 작업의 결과는 비동기적으로 받을 수 밖에 없다. @Async 를 통해 논블로킹/비동기 작업을 수행할 수 있는데 이 자체 목적으로 활용되기도 하고 CompletableFuture 와 조합해서 병렬처리에 활용하기도 한다. 엄밀히 따지면 @Async 역시 별도 스레드를 통해 작업을 수행하는 것이기 때문에 병렬처리라고 볼 수도 있겠지만 여기에서 말하는 병렬처리는..

Backend/Java 2021.07.14

@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

Collections.EMPTY_LIST, Collections.EMPTY_MAP

apache commons-collections 패키지에 보면 Collections.EMPTY_LIST, Collections.EMPTY_MAP 라는 상수가 존재한다. 여기에서는 이걸 왜 사용하는지 정리해본다. 개발을 하다보면 의도적으로 빈객체를 만들어야 하는 상황이 있다. 예를 들어 CircuitBreaker의 fallback 메소드가 그렇다. 정상적인 데이터를 받지 못했지만 임시로 처리하기 위해 기본적인 객체 구조는 갖추되 정말 아무런 값이 필요없는 필드는 빈 객체로 할당해야 한다. 빈 객체를 할당해야 하는 필드가 List 타입이라고 한다면 new ArrayList() 로 할당해도 되겠지만 되도록 Collections.EMPTY_LIST 를 사용하는 편이 좋다. 이유는 아무런 데이터가 없는 빈 객체 ..

Backend/Java 2021.07.12

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
728x90