Java 8 핵심 정리

한눈에 보기

Java 8은 람다와 스트림 API로 함수형 스타일을 정착시킨 자바 최대의 전환점이다. Optional, 디폴트 메서드, java.time, 메타스페이스 도입까지 핵심 변화를 면접 관점에서 정리한다.

최종 업데이트 2026.09.17

Java 8은 2014년에 발표된 자바 역사상 가장 큰 전환점으로, 람다 표현식(Lambda Expression)과 스트림 API(Stream API)를 도입해 자바에 함수형 프로그래밍 스타일을 정착시킨 버전이다. 이와 함께 Optional, 인터페이스의 디폴트 메서드(default method), 새로운 날짜와 시간 API, 영구 세대(PermGen)를 대체한 메타스페이스(Metaspace)까지 언어와 라이브러리와 JVM 전반이 한꺼번에 바뀌었다. 이후 버전들의 기능 대부분이 Java 8의 토대 위에 세워졌기 때문에, 최신 LTS인 Java 21을 쓰는 지금도 면접에서 가장 자주 다뤄지는 버전이다.

람다 표현식과 함수형 인터페이스

람다 표현식은 추상 메서드가 하나뿐인 함수형 인터페이스(functional interface)의 구현을 간결한 식으로 표현하는 문법이다. 익명 클래스로 길게 쓰던 코드가 화살표 하나로 줄어들며, 동작 자체를 값처럼 메서드에 전달할 수 있게 되었다. java.util.function 패키지에 Function, Consumer, Supplier, Predicate 같은 표준 함수형 인터페이스가 함께 추가되었고, 기존 메서드를 그대로 전달하는 메서드 참조(method reference) 문법도 도입되었다.

// Java 7까지의 익명 클래스
Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return a.length() - b.length();
    }
});

// Java 8의 람다와 메서드 참조
names.sort((a, b) -> a.length() - b.length());
names.sort(Comparator.comparingInt(String::length));

람다는 익명 클래스와 달리 컴파일 시 별도 클래스 파일을 만들지 않고 invokedynamic 명령을 통해 실행 시점에 구현체를 생성하며, this가 람다를 감싼 바깥 인스턴스를 가리킨다는 차이가 있다. 람다가 캡처하는 지역 변수는 사실상 final이어야 한다는 제약도 기억해야 한다.

스트림 API와 Optional

스트림 API는 컬렉션 데이터를 선언적으로 처리하는 파이프라인을 제공한다. filter, map 같은 중간 연산을 이어 붙이고 collect, count 같은 최종 연산으로 결과를 얻는 구조이며, parallelStream()으로 손쉽게 병렬 처리도 시도할 수 있다. 반복 방법을 개발자가 기술하던 외부 반복이 라이브러리에 맡기는 내부 반복으로 바뀐 것이 핵심이다.

List<String> result = members.stream()
        .filter(m -> m.getAge() >= 20)
        .map(Member::getName)
        .sorted()
        .collect(Collectors.toList());

Optional<T>는 값이 없을 수 있음을 타입으로 드러내는 컨테이너다. null을 그대로 반환하던 관행을 대체해 NullPointerException을 컴파일 타임 사고방식으로 예방하게 한다. orElse, map, ifPresent 같은 메서드로 값의 존재 여부에 따른 처리를 체이닝할 수 있으며, 반환 타입으로만 쓰고 필드나 매개변수로는 쓰지 않는 것이 권장 관례다.

인터페이스의 진화: 디폴트 메서드와 static 메서드

Java 8부터 인터페이스에 구현부를 가진 디폴트 메서드와 static 메서드를 선언할 수 있게 되었다. 이는 스트림 도입을 위해 Collection 인터페이스에 stream() 등을 추가하면서도 기존 구현체들이 깨지지 않게 하려는 하위 호환 장치였다. 그 결과 인터페이스가 추상 메서드만 갖는다는 전통적 구분이 흐려졌고, 두 인터페이스가 같은 시그니처의 디폴트 메서드를 제공하면 구현 클래스가 명시적으로 재정의해 충돌을 해소해야 하는 다이아몬드 문제가 새로 생겼다.

날짜와 시간 API, 그리고 메타스페이스

기존 Date와 Calendar는 가변 객체에 월이 0부터 시작하는 등 설계 문제가 많았다. Java 8은 java.time 패키지에 LocalDate, LocalDateTime, ZonedDateTime, Duration, Period 같은 불변 타입을 도입해 이를 대체했다. 모든 연산이 새 객체를 반환하므로 스레드 안전하고, 시간대 처리도 명확해졌다.

JVM 차원에서는 클래스 메타데이터를 저장하던 영구 세대가 제거되고 네이티브 메모리를 쓰는 메타스페이스로 대체되었다. 고정 크기였던 영구 세대는 클래스를 많이 로딩하는 애플리케이션에서 OutOfMemoryError: PermGen space를 자주 일으켰는데, 메타스페이스는 기본적으로 필요에 따라 확장되므로 이 문제가 완화되었다. 이 밖에 비동기 작업을 조합하는 CompletableFuture, 원자적 누적에 특화된 LongAdder, Nashorn 자바스크립트 엔진(이후 제거됨) 등도 Java 8에 추가되었다.

Java 8 주요 변화 요약

분류기능의의
언어람다, 메서드 참조, 디폴트 메서드함수형 스타일 도입, 인터페이스 진화
라이브러리Stream API, Optional, java.time, CompletableFuture선언적 데이터 처리와 null 안전성
JVM메타스페이스 도입PermGen 메모리 문제 해소

면접에서 이렇게 물어본다

  • Java 8의 대표 기능을 꼽고 각각이 해결하려던 문제를 설명해 보라.
  • 람다 표현식과 익명 클래스의 차이를 this 바인딩과 컴파일 방식 관점에서 설명해 보라.
  • 인터페이스에 디폴트 메서드가 도입된 배경은 무엇이며 어떤 충돌 문제가 생길 수 있는가.
  • Optional의 올바른 사용법과 쓰지 말아야 할 자리를 설명해 보라.
  • PermGen이 메타스페이스로 대체된 이유와 그 차이를 설명해 보라.
Java 문서 전체 보기

이 개념, 내 코드에서는 어떻게 물어볼까요

데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.

공고 넣고 시작하기