JDK 13 핵심 기능 — 텍스트 블록과 ZGC 개선

Text Blocks (Preview)

Java 13에서 가장 기다려진 기능은 텍스트 블록(JEP 355)입니다. 여러 줄 문자열을 작성할 때 \n+ 연결 지옥에서 벗어날 수 있습니다.

이메일 템플릿을 떠올리면 됩니다. 기존에는 편지 한 줄마다 풀칠해서 붙이는 느낌이었다면, 텍스트 블록은 편지지 한 장에 자연스럽게 쓰는 느낌입니다.

기본 사용법

public class TextBlockBasic {
    public static void main(String[] args) {
        // === 기존 방식: 이스케이프와 연결 연산자의 지옥 ===
        String jsonOld = "{\n" +
            "    \"name\": \"홍길동\",\n" +
            "    \"age\": 30,\n" +
            "    \"city\": \"서울\"\n" +
            "}";

        // === 텍스트 블록: 보이는 그대로 저장 ===
        String jsonNew = """
                {
                    "name": "홍길동",
                    "age": 30,
                    "city": "서울"
                }
                """;

        System.out.println("기존 방식:");
        System.out.println(jsonOld);
        System.out.println();
        System.out.println("텍스트 블록:");
        System.out.println(jsonNew);
        System.out.println("두 문자열 동일? " + jsonOld.equals(jsonNew.strip()));
        // 출력:
        // 기존 방식:
        // {
        //     "name": "홍길동",
        //     "age": 30,
        //     "city": "서울"
        // }
        //
        // 텍스트 블록:
        // {
        //     "name": "홍길동",
        //     "age": 30,
        //     "city": "서울"
        // }
        //
        // 두 문자열 동일? true
    }
}

텍스트 블록은 """(따옴표 세 개)로 시작하고 끝납니다. 시작 """ 뒤에는 반드시 줄바꿈이 와야 합니다. 들여쓰기는 닫는 """의 위치를 기준으로 자동 정렬됩니다.

들여쓰기 제어

텍스트 블록의 들여쓰기는 **공통 선행 공백(common leading whitespace)**이 자동 제거되는 규칙을 따릅니다. 닫는 """의 위치가 기준선입니다.

public class TextBlockIndent {
    public static void main(String[] args) {
        // 닫는 """를 왼쪽으로 옮기면 들여쓰기가 유지됨
        String html = """
<html>
    <body>
        <p>들여쓰기 없음</p>
    </body>
</html>
""";

        // 닫는 """를 오른쪽으로 옮기면 상대적 들여쓰기 적용
        String htmlIndented = """
                <html>
                    <body>
                        <p>4칸 들여쓰기</p>
                    </body>
                </html>
                """;

        System.out.println("들여쓰기 없음:");
        System.out.println(html);
        System.out.println("들여쓰기 적용:");
        System.out.println(htmlIndented);
        // 출력:
        // 들여쓰기 없음:
        // <html>
        //     <body>
        //         <p>들여쓰기 없음</p>
        //     </body>
        // </html>
        //
        // 들여쓰기 적용:
        // <html>
        //     <body>
        //         <p>4칸 들여쓰기</p>
        //     </body>
        // </html>
    }
}

Switch Expressions 개선 — yield 키워드

Java 12에서 프리뷰로 도입된 Switch Expressions가 Java 13에서 한 단계 개선되었습니다(JEP 354). 핵심 변경은 yield 키워드의 도입입니다.

화살표() 문법은 단일 표현식을 반환하기에 적합하지만, 블록 내에서 복잡한 로직 후 값을 반환할 때는 yield를 사용합니다.

public class SwitchYieldDemo {
    public static void main(String[] args) {
        String day = "WEDNESDAY";

        // === 화살표 문법: 단순 값 반환 ===
        int letters = switch (day) {
            case "MONDAY", "FRIDAY", "SUNDAY" -> 6;
            case "TUESDAY" -> 7;
            case "WEDNESDAY", "THURSDAY", "SATURDAY" -> {
                // 블록이 필요한 경우 yield로 값 반환
                System.out.println(day + " 처리 중...");
                yield day.length();
            }
            default -> throw new IllegalArgumentException("알 수 없는 요일: " + day);
        };

        System.out.println(day + " → " + letters + "글자");

        // === 콜론(:) 문법에서도 yield 사용 가능 ===
        String season = switch (day) {
            case "MONDAY":
            case "TUESDAY":
                yield "평일 초반";
            case "WEDNESDAY":
                yield "주 중간";
            case "THURSDAY":
            case "FRIDAY":
                yield "평일 후반";
            default:
                yield "주말";
        };

        System.out.println(day + " → " + season);
        // 출력:
        // WEDNESDAY 처리 중...
        // WEDNESDAY → 9글자
        // WEDNESDAY → 주 중간
    }
}

yield는 switch 표현식 전용 키워드입니다. break가 값을 반환하던 Java 12의 방식(break value;)을 대체합니다. 이 변경으로 break는 루프 제어, yield는 switch 값 반환이라는 명확한 역할 분리가 이루어졌습니다.

ZGC 메모리 반환 (JEP 351)

ZGC(Z Garbage Collector)는 Java 11에서 실험적으로 도입된 저지연 GC입니다. Java 13에서는 미사용 힙 메모리를 OS에 반환하는 기능이 추가되었습니다.

이전에는 ZGC가 한 번 확보한 메모리를 계속 들고 있었습니다. 트래픽 급증 후 메모리가 원래 수준으로 돌아오지 않아 컨테이너 환경에서 비효율적이었습니다.

# ZGC 활성화 및 메모리 반환 설정
java -XX:+UnlockExperimentalVMOptions \
     -XX:+UseZGC \
     -XX:ZUncommitDelay=300 \
     -jar your-app.jar

# ZUncommitDelay: 미사용 메모리 반환까지 대기 시간 (초, 기본 300)
환경기대 효과
쿠버네티스 Pod트래픽 감소 시 메모리 반환 → 클러스터 자원 절약
공유 서버유휴 애플리케이션의 메모리 회수
개발 환경여러 JVM 프로세스의 메모리 사용량 감소

Socket API 재구현 (JEP 353)

java.net.Socketjava.net.ServerSocket의 내부 구현이 NioSocketImpl로 교체되었습니다. 기존 구현(PlainSocketImpl)은 JDK 1.0 시절부터 이어져 온 레거시 코드였습니다.

외부 API는 동일하므로 기존 코드 변경은 필요 없습니다. 내부적으로 NIO 기반으로 전환되어 유지보수성이 향상되고, 이후 Virtual Thread(Java 21)와의 통합 기반이 마련되었습니다.

Dynamic CDS Archives (JEP 350)

**CDS(Class Data Sharing)**는 JVM 시작 시간을 줄이는 기술입니다. 클래스 메타데이터를 공유 아카이브에 미리 저장해두고, 다음 실행 시 재활용합니다.

Java 13에서는 애플리케이션 종료 시점에 자동으로 CDS 아카이브를 생성할 수 있게 되었습니다. 이전에는 별도의 trial run이 필요했습니다.

# 1단계: 애플리케이션 실행하면서 CDS 아카이브 자동 생성
java -XX:ArchiveClassesAtExit=app-cds.jsa -jar your-app.jar

# 2단계: 다음 실행부터 아카이브 활용 → 시작 시간 단축
java -XX:SharedArchiveFile=app-cds.jsa -jar your-app.jar

마이크로서비스 환경에서 수십 개 인스턴스가 동시에 시작하는 경우, CDS로 시작 시간을 20~30% 단축할 수 있습니다.

실전 팁

기능활용 포인트
Text BlocksJSON, HTML, SQL 등 여러 줄 문자열에 즉시 적용
yieldswitch 블록 내 복잡한 로직이 있을 때 사용
ZGC 메모리 반환컨테이너 환경에서 메모리 효율 개선
Dynamic CDS마이크로서비스 시작 시간 최적화
NioSocketImpl코드 변경 없이 자동 적용 (Java 13+ 사용 시)

Java 13은 “큰 변화”보다는 기존 기능의 성숙에 초점을 맞춘 릴리스입니다. Text Blocks는 이후 Java 15에서 정식 확정되고, Switch Expressions의 yield 키워드는 Java 14에서 정식으로 굳어집니다. 이 시기의 프리뷰 기능들이 모두 Java 14~15에서 정식이 되므로, Java 13은 “전환기의 다리” 역할을 한 버전입니다.

이 글이 도움이 되었나요?