포스트

2022-09-21-TIL

2022-09-21-TIL

Today I Learned

Java Stream vs For-loop

Stream API가 for 루프보다 느리다는 이야기는 자주 나오지만 조건이 붙는다. 기본형 배열을 단순히 더하는 정도의 아주 가벼운 연산에서는 스트림 파이프라인을 구성하는 객체 생성, 람다 호출, 박싱 비용이 상대적으로 커서 for 루프가 빠르게 나올 수 있다. 반대로 요소마다 하는 일이 무거워지면 그 차이는 전체 시간에서 묻힌다. 그래서 일반적인 비즈니스 코드에서는 가독성을 기준으로 고르고, 성능이 문제 되는 구간만 측정해서 바꾸는 편이 낫다. 측정할 때는 JIT 워밍업 영향을 받지 않도록 JMH 같은 도구를 써야 한다.

병렬 스트림도 마찬가지다. Baeldung 글에 따르면 parallelStream()은 Java 7에 추가된 fork-join 프레임워크의 공용 풀(ForkJoinPool.commonPool())에서 작업을 나눠 실행한다. 데이터를 나누고 결과를 합치는 비용, 메모리 지역성을 고려하면 항상 빠른 것은 아니다. 또 공용 풀은 애플리케이션 전체가 함께 쓰므로, 웹 서버에서 블로킹 I/O를 병렬 스트림으로 돌리면 다른 병렬 작업까지 느려질 수 있다.

대량 데이터를 일정 크기로 끊어 처리(batch)하는 것은 스트림에 기본 연산이 없어서, 리스트를 인덱스 기준으로 나누거나 반복문으로 묶는 방식을 쓴다.

  • https://jypthemiracle.medium.com/java-stream-api%EB%8A%94-%EC%99%9C-for-loop%EB%B3%B4%EB%8B%A4-%EB%8A%90%EB%A6%B4%EA%B9%8C-50dec4b9974b
  • http://www.angelikalanger.com/Conferences/Videos/Conference-Video-GeeCon-2015-Performance-Model-of-Streams-in-Java-8-Angelika-Langer.html
  • https://jeong-pro.tistory.com/185
  • https://stackoverflow.com/questions/30641383/java-8-stream-with-batch-processing
  • https://blog.jdriven.com/2019/10/loop/
  • https://www.baeldung.com/java-when-to-use-parallel-stream

대용량 Excel 파일 효율적으로 쓰기

Apache POI의 XSSFWorkbook은 시트 전체를 메모리에 올린 채로 작업한다. 행이 수십만 건을 넘으면 힙이 부족해진다. 링크 글은 100만 행을 쓰는 두 방법을 비교한다. 데이터 소스에서 5,000건씩 가져올 때마다 파일을 열어 덧붙이는 방법은 약 3GB의 힙과 1분 56초가 들었고, 스트리밍 API인 SXSSFWorkbook으로 쓰는 방법은 약 350MB와 5초가 들었다고 한다. 저자의 환경에서 측정한 값이다.

SXSSFWorkbook은 정해진 개수(기본 100행)의 행만 메모리에 두고, 창을 벗어난 행은 임시 파일로 내보낸다. 내보낸 행은 다시 읽거나 수정할 수 없고, 기존 파일에 덧붙이는(append) 모드로 열 수도 없다. 작업이 끝나면 dispose()로 임시 파일을 지워야 한다(Apache POI: SXSSF).

1
2
3
4
5
6
7
8
9
10
11
try (SXSSFWorkbook wb = new SXSSFWorkbook(100)) {
    Sheet sheet = wb.createSheet("report");
    int rowNum = 0;
    for (Order order : orders) {
        Row row = sheet.createRow(rowNum++);
        row.createCell(0).setCellValue(order.getId());
        row.createCell(1).setCellValue(order.getAmount());
    }
    wb.write(out);
    wb.dispose();
}
  • https://levelup.gitconnected.com/how-to-write-a-million-rows-in-an-excel-file-efficiently-5f7ce6c69314

Batch Service

Spring Batch는 대량 데이터를 읽고, 가공하고, 쓰는 작업을 Job과 Step 단위로 구성하는 프레임워크다. Step 하나는 보통 ItemReader, ItemProcessor, ItemWriter로 이루어지고, 일정 개수(chunk)씩 읽어 처리한 뒤 한 트랜잭션으로 쓴다. 실행 이력과 진행 상태를 메타데이터 테이블에 남기기 때문에 실패한 지점부터 재시작할 수 있다. Spring 가이드는 CSV 파일을 읽어 변환한 뒤 DB에 저장하는 예제로 이 구조를 보여 준다. Keyhole 글은 대용량 엑셀 생성을 Spring Batch로 처리하는 방법을 다룬다. 이렇게 배치 작업으로 분리하면 사용자 요청 스레드가 오래 붙잡히지 않고 결과 파일을 나중에 내려받게 할 수 있다.

  • https://spring.io/guides/gs/batch-processing/
  • https://keyholesoftware.com/2012/11/12/generating-large-excel-files-using-spring-batch-part-three/

Serverless Architecture

서버리스는 서버가 없다는 뜻이 아니라, 서버 프로비저닝과 확장, 운영을 클라우드 사업자에게 맡기는 방식이다. 대표적인 형태는 이벤트가 올 때만 함수가 실행되고 실행 시간만큼 과금되는 FaaS(AWS Lambda 등)다. 트래픽이 들쭉날쭉한 서비스에서 비용과 확장 부담이 줄어드는 대신, 오래 쉬던 함수가 처음 호출될 때 지연(콜드 스타트)이 생기고, 실행 시간 제한과 특정 사업자 종속을 받아들여야 한다. 두 번째 링크는 이커머스 서비스를 서버리스로 운영한 경험을 다룬 글이다.

  • https://velopert.com/3543
  • https://medium.com/@kurtlee/serverless%EB%A1%9C-e-commerce-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B8%94%EB%9E%99%ED%94%84%EB%9D%BC%EC%9D%B4%EB%8D%B0%EC%9D%B4-%ED%8A%B8%EB%9E%98%ED%94%BD-%EC%8D%B0-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85%EC%97%90%EC%84%9C-cto%EB%8A%94-%EB%AD%98-%ED%95%98%EB%8A%94-%EC%9E%90%EB%A6%AC%EC%9D%B8%EA%B0%80-a6f9d9beb930

www.google.com 입력했을 때 일어나는 과정

면접 단골 질문이다. 큰 흐름은 다음과 같다.

  1. 브라우저가 URL을 해석하고, 브라우저·OS 캐시에서 도메인의 IP를 찾는다. 없으면 DNS 리졸버에 질의한다.
  2. 얻은 IP로 TCP 연결을 맺고(3-way handshake), HTTPS이므로 TLS 핸드셰이크로 암호화 키를 협상한다.
  3. HTTP 요청을 보내고, 서버(앞단의 로드밸런서와 웹 서버, 애플리케이션 서버)가 응답한다.
  4. 브라우저가 HTML을 파싱해 DOM을 만들고 CSS, JS, 이미지 같은 하위 리소스를 추가로 요청한 뒤 화면을 그린다.
  • https://velog.io/@tnehd1998/%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90-www.google.com%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%96%88%EC%9D%84-%EB%95%8C-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EA%B3%BC%EC%A0%95

백엔드 개발 학습자료

백엔드 학습 자료 링크 모음이다.

  • https://velog.io/@frankle97/backend-study-collection
참고한 자료외부 출처 3

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다