포스트

2023-06-10-TIL

2023-06-10-TIL

Today I Learned

GraalVM

GraalVM은 Java 애플리케이션을 미리(ahead-of-time) 네이티브 실행 파일로 컴파일하는 Native Image로 잘 알려져 있다. 공식 사이트는 네이티브 실행 파일이 JVM에 비해 메모리와 CPU를 일부만 쓰고, 워밍업 없이 바로 시작하며, 애플리케이션에 필요한 클래스와 메서드, 필드만 담는다고 설명한다. Spring Boot, Micronaut, Quarkus 같은 프레임워크도 이를 지원한다(GraalVM). 시작 시간이 중요한 서버리스나 컨테이너 환경에서 장점이 크다. 대신 빌드 시점의 정적 분석으로 포함할 코드를 정하기 때문에, 리플렉션이나 리소스 접근처럼 실행 중에야 대상이 정해지는 부분은 reachability metadata로 따로 알려 줘야 한다(Native Image: Reachability Metadata).

  • https://www.graalvm.org/

Java vs .NET

JVM과 .NET의 CLR은 구조가 닮았다. 둘 다 소스 코드를 중간 언어(자바 바이트코드, CIL)로 컴파일하고, 런타임이 이를 실행하면서 메모리 관리(GC)를 맡는다. CLR의 타입 시스템과 메타데이터 형식은 ECMA CLI 명세로 공개되어 있다(Microsoft: CLR overview).

눈에 띄는 차이는 제네릭이다. 자바는 타입 소거(type erasure)로 제네릭을 구현해서, 컴파일 후 타입 파라미터가 경계 타입이나 Object로 바뀌고 List<String>과 List<Integer>가 같은 클래스가 된다(Java Tutorials: Type Erasure). .NET은 CIL에 타입 파라미터 정보가 남고, 값 타입으로 만들 때마다 런타임이 특화된 타입을 만든다. 그래서 실행 중에도 리플렉션으로 실제 타입 인자를 알 수 있다(Microsoft: Generics in the runtime).

  • https://devm.io/java/java-net-clr-jvm-173213

Java Caching System

Apache Commons JCS는 자바로 작성된 분산 캐시 시스템이다. 메모리(LRU), 디스크, 다른 서버로 퍼뜨리는 lateral(TCP), 중앙 서버를 두는 remote(RMI) 캐시를 조합할 수 있다. 문서는 읽기가 많고 쓰기가 적은 애플리케이션에서 가장 유용하다고 적는다(Apache Commons JCS).

  • https://commons.apache.org/proper/commons-jcs/

JetBrains Exposed

Exposed는 JetBrains가 만든 Kotlin용 경량 SQL 라이브러리다. SQL을 타입 안전하게 감싼 DSL 방식과, 객체로 접근하는 가벼운 DAO 방식 두 가지를 제공하고 H2, MySQL, PostgreSQL, Oracle 등 여러 DB를 지원한다(JetBrains/Exposed). 특히 DSL 방식은 Kotlin 코드가 거의 그대로 SQL 문장에 대응한다.

  • https://github.com/JetBrains/Exposed

Stop Using JPA/Hibernate

JPA를 쓰지 말자는 의견 글이다. 저자는 Hibernate 문서가 400쪽이 넘을 만큼 복잡하고, 기본 생성자와 변경 가능한 getter를 요구해 객체의 불변식을 깨며, 지연 로딩과 자동 flush가 디버깅을 어렵게 하고, 필드 하나가 필요해도 엔티티 전체를 읽는다고 비판한다. 대안으로 SQL을 직접 쓰고, 이미 JPA를 쓰는 프로젝트라면 JPA를 인프라 계층에 가두고 도메인 모델과 분리하라고 권한다.

글의 주장 중 “JPA를 인프라 계층에 가두라”는 부분은 JPA를 계속 쓰더라도 적용할 수 있다.

  • https://www.stemlaur.com/blog/2021/03/30/tech-hibern-hate/

Cachex

Cachex는 Elixir용 인메모리 캐시 라이브러리다. Erlang/OTP의 ETS 위에 만들어졌고, 시간 기반 만료, 최대 크기 제한, 실행 전후 훅, 캐시 워밍, 행 잠금을 쓰는 트랜잭션, 통계 같은 기능을 필요한 것만 골라 켤 수 있다(Cachex).

  • https://hexdocs.pm/cachex/Cachex.html

Java Distributed Cache

서버를 여러 대 띄우면 각 서버의 로컬 캐시 내용이 서로 달라진다. 분산 캐시는 캐시를 여러 노드가 공유하게 해서 이 문제를 푼다. Hazelcast는 데이터를 메모리에 두고 클러스터의 여러 머신에 나누어 복제하는 분산 저장, 계산 플랫폼이다(Hazelcast Documentation).

링크한 글은 Spring Boot와 Hazelcast를 붙이는 두 가지 토폴로지를 비교한다. 임베디드 방식은 애플리케이션마다 Hazelcast 멤버가 함께 떠서 네트워크 없이 빠르게 읽지만, 인스턴스가 많아질수록 메모리와 복제 비용이 커진다. 클라이언트-서버 방식은 캐시 클러스터를 따로 두어 애플리케이션과 캐시를 독립적으로 확장할 수 있지만 매번 네트워크를 거친다. 이를 줄이려고 클라이언트 쪽에 near cache를 두기도 한다.

  • https://reflectoring.io/spring-boot-hazelcast/
참고한 자료외부 출처 9

외부 출처

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

댓글

아직 댓글이 없습니다