💡 핵심 요약 (Executive Summary)
본 가이드는 java 핵심 가이드 및 실전 아키텍처의 핵심 개념, 실전 구성 명령어 및 아키텍처 베스트 프랙티스를 다룹니다. 클라우드 네이티브 및 인프라 엔지니어링 실무에 즉시 활용 가능하도록 체계적으로 정리했습니다.
📑 Table of Contents
하위페이지
Spring
Roadmap
Java Collection
Map
Object → Map (Jackson.ObjectMapper)
java
ObjectMapper objectMapper = new ObjectMapper();
Person person = new Person(12, "kim");
Map<String, Object> map = objectMapper.convertValue(person, Map.class);
Map → String for Logging (Collection.Stream)
java
String resultSet =
{{ map_var }}.entrySet()
.stream()
.map(e -> e.getKey() + "=" + String.join(", ", e.getValue()))
.collect(Collectors.joining(" "));
log.debug(resultSet);
...
List
Array Parse with List (Lists or Arrays)
java
// List to Array
long[] longArr = Longs.toArray(longList);
// List to Array (Object)
String[] strArr = StringList.toArray(new String[0]);
// Array to List
Integer[] sourceArray = { 0, 1, 2, 3, 4, 5 };
List<Integer> targetList = Lists.newArrayList(sourceArray);
List<String> targetList2 = Arrays.asList(new String[] {""});
JSON
Object → JsonString (Jackson.ObjectMapper)
Object -> Json 변환과정은 Serialization 이라고 한다. Jackson은 String 이외에 file이나 stream에 쓰는것도 가능하다.
java
ObjectMapper objectMapper = new ObjectMapper();
Person person = new Person("Nicole", 20);
String personJson = objectMapper.writeValueAsString(person);
System.out.println(personJson);
JsonString → Object (Jackson.ObjectMapper)
Json -> Object 변환 과정은 Deserialization 이라고 한다. Serialization과 마찬가지로 file이나 stream에 쓰는것도 가능하다.
java
String personJson = "{isJsonString}"
Person jsonToPerson = objectMapper.readValue(personJson, Person.class);
Reactive Streams
| 비교 항목 | Java Stream API | WebFlux (Project Reactor) |
| 작동 방식 | Pull-based (동기) | Push-based (비동기) |
| Blocking 여부 | Blocking. 데이터를 다 모을 때까지 스레드가 대기함. | Non-blocking. 데이터가 준비되면 알려달라고 예약함. |
| 데이터 소스 | 이미 메모리에 있는 컬렉션 (List, Set 등) | 언제 올지 모르는 데이터 흐름 (네트워크, DB 등) |
| 사용 목적 | 대량의 데이터를 빠르게 계산 (병렬 처리 등) | 적은 스레드로 많은 동시 요청을 효율적 처리 |
| 재사용성 | 한 번 소비하면 끝 (닫힘) | 여러 번 구독(Subscribe) 가능 |
Java Stream
java
/* Stream.map() */
List<?> baseList = new ArrayList<>();
List<?> rtnList = baseList.stream().map(obj->{
return obj.value
}).collect(Collectors.toList());
/** Map 내 모든 리스트 병합 */
((HashMap<String,List<String>>) obj).values().stream().flatMap(List::stream).collect(Collectors.toList()));
/** 표현식 설명 아래 모두 기능 동일*/
// .A(B::C) 종류 (.A(D->{})를 가정)
// 1. .A(D->D.C())
.map(Map.Entry::getValue) == .map(entry -> entry.getValue())
// 2. Consumer<T(D)> void : .A(D->B.C(D))
.forEach(System.out::println) == .forEach(item -> System.out.println(item))
// 3. Supplier<T(new)> retrun T : .A(()->B.C())
(Math::random) == (()->Math.random())
// 4. Function<T(D),T(B)> ? : .A(D->B.C(D))
(Interger::parseInt) == (str->Integer.parseInt(str));
// 5. Predicate<T(B)> return Boolean : .A(D->D.C())
(String::isEmpty)
// 이것을 단순화하려 해보았지만, 분석결과 사실 Functional Interface의 정의에 따라 모두 다른 결과일것으로 보임
WebFlux (Project Reactor)
java
//ClientRequest
//ClientResponse
response.bodyToMono()
//Body and Mono
Publisher.subscribe(
value -> { //when then (Published value)
},
error -> { //when throwed
},
() -> { //when completed
}
)
실패
java
//ClientResponse를 Publisher(bodyToMono(), bodyToFlux())를 사용하여 로깅
//외부 웹클라이언트의 이벤트에 의해 다중실행되는 메서드이므로 subscribe()-비동기-를 하게되면 에러발생.
/** 에러 예시 */
clientResponse.bodyToMono(String.class)
.doOnNext(responseBody -> {
sb.append("\tBody: \n");
sb.append("\t\tContents: " + responseBody + " \n");
})
.doOnTerminate(()-> {
log.info(sb.toString());
})
.subscribe();
return Mono.just(clientResponse);
/** 잘못된 예시 */
clientResponse.bodyToMono(String.class)
.flatMap(responseBody -> {
sb.append("\tBody: \n");
sb.append("\t\tContents: " + responseBody + " \n");
log.info(sb.toString());
return Mono.empty();
});
return Mono.just(clientResponse);
/*
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2
이 메시지는 다음을 나타냅니다:
block(), blockFirst(), 또는 blockLast()와 같은 블로킹 연산을 스레드 "reactor-http-nio-2"에서 사용하고 있다는 것입니다.
Reactor는 비동기 및 논블로킹 스트림 처리를 위해 설계되었으므로 블로킹 연산을 사용하면 문제가 발생할 수 있습니다.
*/
/** 방법 */
clientResponse.bodyToMono(String.class)
.subscribeOn(Schedulers.elastic())
.subscribe(responseBody -> {
sb.append("\tBody: \n");
sb.append("\t\tCount: " + JsonParserFactory.getJsonParser().parseMap(responseBody).size() + " \n");
sb.append("\t\tContents: " + responseBody + " \n");
log.info(sb.toString());
});
// }
return Mono.just(clientResponse);
/* Steam을 즉시 종료하고 내용물을 꺼내기 */
Mono<String> mono = Mono.just("Hello, Reactor!");
mono
.take(1)
.subscribe(
value -> {
// 첫 번째 요소를 처리합니다.
System.out.println("Received value: " + value);
},
error -> {
// 에러 처리
},
() -> {
// 완료 처리
}
);
| 메서드 | 입력(Input) | 출력(Output) | 리액터의 처리 (Unwrapping) |
map
|
T
|
R (일반 객체)
|
받은 그대로 다음 단계로 넘김 |
flatMap
|
T
|
Mono 또는 Flux
|
상자를 까서 알맹이 R만 꺼내 다음 단계로 넘김
|
flatMapMany
|
T
|
Flux
|
Mono를 여러 개의 알맹이가 흐르는 Flux로 확장함
|
flatMapIterable
|
T
|
Iterable (List 등)
|
리스트를 하나씩 쪼개서 순차적으로 내보냄 |




Leave a Reply