개발
자바 스프링 개발 시작하기 - 5일차 모던 Java 스킬업
스택큐힙리스트
2025. 7. 11. 12:13
반응형
1. 오늘의 목표
람다‧Stream‧Record‧Optional 네 가지 키워드를 활용해 실시간 로그를 필터링하고 집계하는 예제를 만들며 “함수형 사고”에 감 잡기. 프로젝트 전반에서 반복될 깨끗한 데이터 파이프라인을 설계할 토대를 다집니다.
2. 왜 배워야 할까?
- 람다식으로 익명 클래스를 걷어내 코드량 ↓, 가독성 ↑.
- Stream API로 멀티스레드 컬렉션 처리까지 한 줄에.
- Record로 DTO 보일러플레이트 제거, 불변 객체 기본화.
- Optional로 NullPointerException 방지 & “null 체크” 관습 탈출.
3. 실습 – 실시간 로그 필터·집계 파이프라인
// Record: 로그 한 줄 정의
public record LogLine(long ts, String level, String msg) {}
// (1) 스트림 파이프라인 – 필터 → 매핑 → 집계
Map<String, Long> errorCounts =
logStream() // 실시간 스트림(예: KafkaConsumer records)
.map(LogParser::toLogLine) // 문자열 → LogLine(Record)
.filter(l -> l.level().equals("ERROR"))
.collect(Collectors.groupingBy(
LogLine::msg, Collectors.counting()));
// (2) Optional 활용 – 가장 흔한 에러 메시지 출력
errorCounts.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.ifPresentOrElse(
m -> System.out.println("TOP ERROR ▶ " + m),
() -> System.out.println("No errors 🎉"));
핵심 포인트
- filter()에 람다식 전달해 ERROR 레벨만 추출.
- groupingBy로 실시간 카운트; 필요하면 Collectors.toConcurrentMap으로 교체해 병렬 집계.
- Optional.ifPresentOrElse로 결과가 없을 때도 깔끔한 분기 처리.
4. 실전 적용 팁
- Record vs Lombok
Record는 JDK 14+ 정식 포함. @Getters나 @AllArgsConstructor 없이도 equals/hashCode 자동 제공 → 간결성 & 유지보수성 상승. - Stream 성능
대량 데이터라면 parallel()을 고민하되 CPU 코어·스레드풀 상황을 먼저 체크. 무차별 parallel()은 오히려 병목. - Optional 남용 금지
필드나 파라미터보단 리턴 타입 에만 사용 → 불필요한 객체 생성 방지. - 테스트 전략
Stream 파이프라인은 단계별로 peek() 대신 JUnit5 매개변수 테스트를 활용하여 기대 출력값을 검증.
5. 마무리 & 내일 예고
오늘 배운 함수형 도구들은 앞으로 컨트롤러·서비스·레포지토리 층 어디서든 “한 줄 파이프라인”으로 재사용됩니다.
반응형