1. Chapter1 - 자바 8을 눈여겨봐야 하는 이유
자바 역사를 통틀어 가장 큰 변화가 자바 8에서 일어남.
자바 8 덕분에 더 쉽게 프로그램을 구현할 수 있게 됨.
- 자연어에 더 가깝게 간단한 방식으로 코드 구현 가능.
멀티코어 CPU 대중화와 같은 하드웨어적인 변화도 자바 8에 영향을 줌.
- 지금까지의 대부분의 자바 프로그램은 이들 코어 중 하나만을 사용.
- 자바 8 이전에는 나머지 코어를 활용하려면 스레드를 사용사는 것이 좋다고 누군가 조언을 했을 것.
> 하지만 스레드를 사용하면 관리가 어렵고 많은 문제를 야기.
- 자바 1.0에서는 스레드와 락, 메모리 모델까지 지원.
> 특별 전문가로 구성된 프로젝트팀이 아닌 한 이와 같은 저수준 기능을 활용하기 어려움.
- 자바 5에서는 스레드 풀, 병렬 실행 컬렉션 등을 도입.
- 자바 7에서는 병렬 실행에 도움을 줄 수 있는 포크/조인 프레임워크 제공.
> 여전히 개발자가 활용하기에는 어려움.
- 자바 8에서는 병렬 실행을 새롭고 단순한 방식으로 접근할 수 있는 방식 제공.
간결한 코드와 멀티코어 프로세서의 간단한 활용이 자바 8을 구성하는 핵심적인 사항.
자바 8에서 제공하는 새로운 기술.
- 스트림 API
- 메서드에 코드를 전달하는 기법
- 인터페이스의 디폴트 메서드
자바 8은 데이터베이스 질의 언어에서 표현식을 처리하는 것 처럼 병렬 연산을
지원하는 스트림이라는 새로운 API를 제공.
> 스트림을 이용하면 에러를 자주 일으키며 멀티코어 CPU를 이용하는 것보다
비용이 훨씬 비싼 synchronized를 사용하지 않아도 됨.
결국 스트림 API 덕분에 "메서드에 코드를 전달하는 기법(메서드 레퍼런스와 람다)"과
인터페이스의 "디폴트 메서드"가 추가되었음을 알수 있음.
> 하지만 스트림 API 때문에 "메서드에 코드를 전달하는 기법"이 생겼다고 추리하는 것은
메스드에 코드를 전달하는 기법의 활용성을 제한할 위험이 있음.
> 메서드에 코드를 전달하는 기법을 이용하면 새롭고 간결한 방식으로
"동작 파라미터화"를 구현할 수 있음.
메서드에 코드를 전달하는 자바8 기법은 함수형 프로그래밍에서 위력을 발휘
1. 자바가 변화하는 이유?
- 프로그래밍 언어 생태계에도 변화가 시작됨.
- 빅데이터라는 도전에 직면하기 시작하고, 멀티코어 컴퓨터나 컴퓨팅 클러스터를 이용해서
빅데이터를 효과적으로 처리하고자 하는 욕구가 생김.
- 즉, 병렬 프로세싱을 활용해야 하는데 지금까지의 자바로는 충분히 대응하지 못하는 분야.
- 자바8에 추가된 기능은 자바에 없던 완전히 새로운 개념이지만 현 재 시장에서 요구하는 기능을
효과적으로 제공.
- 병렬성을 활용하는 코드, 간결한 코드를 구현할 수 있도록 자바8에서
세 가지의 프로그래밍 개념을 제공.
> 스트림 처리.
> 동작 파라미터화로 메서드에 코드 전달하기
> 병렬성과 공유 가변 데이터
1.1 스트림 처리.
- 스트림이란 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임.
- 이론적으로 프로그램은 입력 스트림에서 데이터를 한 개씩 읽어 들이며 마찬가지로
출력 스트림으로 데이터를 한 개씩 기록.
- 자바 8에는 java.util.stream 패키지에 스트림 API가 추가 됨.
- 스트림 API의 핵심은, 기존에는 한 번에 한 항목을 처리했지만,
이제 자바 8에서는 고 수준으로 추상화해서 일련의 스트림으로 만들어 처리할 수 있다는 것.
- 스트림 파이프라인을 이용해서 입력 부분을 여러 CPU코어에 쉽게 할당 할 수 있다는
부가적 이득도 존재.
- 스레드라는 복잡한 작업을 사용하지 않으면서도 공짜로 병렬성을 얻을 수 있음.
1.2 동작 파라미터화로 메서드에 코드 전달하기
- 코드 일부를 API로 전달하는 기능.
- 자바 8에서는 메서드를 다른 메서드의 인수로 넘겨주는 기능을 제공
> 이론적으로 동작 파라미터화 (behavior parameterization)라 부름.
- 스트림 API는 어떤 동작을 파라미터화할 수 있는 코드를 넘겨줄 수 있는 기능을 제공.
1.3 병렬성과 공유 가변 데이터
- 스트림 메서드로 전달하는 코드는 다른 코드와 동시에 실행 하더라도
안전하게 실행될 수 있어야 함.
- 보통 다른 코드와 동시에 실행 하더라도 안전하게 실행 할 수 있는 코드를
만드려면 공유된 가변 데이터에 접근하지 않아야 함.
> 이러한 함수를 순수 함수(pure), 부작용 없는 함수(side-effect-free)
,상태없는 함수(stateless)라고 함.
- 자바8 스트림을 이용하면 기존 자바 스레드 API보다 쉽게 병렬성을 활용할 수 있음.
- 공유되지 않은 가변 데이터, 메서드와 함수 코드를 다른 메서드로 전달하는 두가지 기능은
함수형 프로그래밍 패러다임의 핵심적 사항.
1.4 자바가 진화해야하는 이유
- 기존 값을 변화시키는 데 집중했던 고전적인 객체지향에서 벗어나
함수형 프로그래밍으로 다가섰다는 것이 자바 8의 가장 큰 변화.
- 함수형 프로그래밍에서는 우리가 하려는 작업이 최우선시되며
그 작업을 어떻게 수행 하는지는 별개 문제로 취급.
- 함수형 프로그래밍을 도입 함으로써 두 가지 프로그래밍 패러다임의 장점을 모두 활용이 가능.
> 전통적인 객체지향 프로그래밍과 자바8에서 도입한 함수형 프로그래밍
2가지 장점 모두 활용.
- 언어는 하드웨어나 프로그래머 기대의 변화에 부응할 수 있도록 변화해야 함.
2. 자바 함수
- 프로그래밍 언어에서 함수(function)라는 용어는 메서드(method),
특히 정적 메서드와 같은 의미로 사용.
- 자바 8에서는 함수를 새로운 값의 형식으로 추가. 병렬 프로그래밍을 활용할 수 있는
스트림과 연계될 수 있도록 함수를 만들었기 때문임.
- 자바에서 조작할 수 있는 값은 아래와 같음.
> 1. int형, double형등의 기본값
> 2. 객체
* new 또는 팩토리 메서드 또는 라이브러리 함수를 이용해서 객체의 값을 얻을 수 있음.
- 프로그래밍 언어의 핵심은 값을 바꾸는 것.
- 위에 언급한 값들은 일급값이지만 메서드, 클래스등은 이급값으로 분류됨.
> 이급값은 프로그램을 실행하는 동안 구조체를 자유롭게 전달할 수 없는 값을 칭함.
- 인스턴스화 하면서 값이 되는 클래스를 정의할 때 메서드를 아주 유용하게 활용할 수 있지만,
메서드와 클래스 그 자체로 값이 될 수 없음.
- 메서드를 일급값으로 만들면 프로그래밍에서 유용하게 사용 가능.
2.1 메서드와 람다를 일급값으로.
- 스칼라와 그루비 같은 언어에서 메서드를 일급값으로 사용하면
프로그래머가 활용할 수 있는 도구가 다양해지면서 프로그래밍이 수월해 진다는 사실을
이미 실험을 통해 확인됨.
- 첫번째로 메서드 레퍼런스(method reference)
> ex) File::isHedden (:: -> 해당 표시를 메서드 레퍼런스라고 함.)
> ::의 의미는 "이 메서드를 값으로 사용하라"는 의미.
- 자바 8에서는 메서드는 일급값으로 취급.
- 기존에 객체 레퍼런스를 이용해서 객체를 이리저리 주고받았던 것 처럼
자바 8에서는 메서드 레퍼런스를 이용해 전달할 수 있게 됨.
@ 람다: 익명함수
- 자바 8에서는 메서드를 일급값으로 취급할 뿐 아니라
람다(또는 익명함수)를 포함하여 함수도 값으로 취급.
- 람다 문법 형식으로 구현된 프로그램을 함수형 프로그래밍,
즉, '함수를 일급값으로 넘겨주는 프로그램을 구현한다'라고 함.
2.2 메서드 전달에서 람다로
- 메서드를 값으로 전달하는 것은 분명 유용한 기능임.
- 하지만 한두 번만 사용할 메서드를 매번 정의하는 것은 귀찮은 일.
- 자바 8에서는 람다를 이용해 처리가 가능.
- 람다를 통한 표현이 복잡해 질 경우 메서드 레퍼런스를 이용하는 것이 바람직함.
> 코드의 명확성이 우선시 되어야 하기 때문임.
3. 스트림
- 거의 모든 자바 어플리케이션은 컬렉션을 만들고 활용함.
> 하지만 모든 컬렉션으로 모든 문제가 해결되는 것은 아님.
- 스트림 API와 컬렉션 API와는 상당히 다른 방식으로 데이터를 처리할 수 있음.
- 컬렉션에서는 반복 과정을 직접 처리.
> 즉, for-each 루프를 이용하여 각 요소를 반복하면서 작업을 수행.
> 이런 방식의 반복을 외부 반복 이라고 함.
- 스트림API를 이용하면 루프를 신경쓸 필요가 없음.
> 라이브러리 내부에서 모든 데이터가 처리 됨.
> 이와 같은 반복을 내부 반복 이라고 함.
3.1 멀티스레딩은 어렵다.
- 이전 자바 버전에서 제공하는 스레드 API로 멀티스레딩 코드를 구현해서
병렬성을 이용하는 것은 쉽지 않음.
- 멀티스레딩 환경에서 각각의 스레드는 동시에 공유된 데이터에 접근,
데이터를 갱신 할 수 있음.
- 결과적으로 스레드를 잘 제어하지 못하면 원치 않은 방식으로 데이터가 바뀔수 있음.
- 자바 8은 스트림 API로 '컬렉션을 처리하면서 발생하는 모호함과 반복직인 코드 문제'
그리고 '멀티코어 활용 어려움'이라는 두가지 문제 모두 해결.
- 컬렉션은 어떻게 데이터를 저장하고 접근 할지에 중점을 두는 반면
스트림은 데이터에 어떤 계산을 할 것인지 묘사하는 것에 중점.
- 스트림은 스트림 내의 요소를 쉽게 병렬처리할 수 있는 환경을 제공한 다는 것이 핵심.
4. 디폴트 메서드
- 자바 8에서는 라이브러리 설계자가 더 쉽게 변화할 수 있는 인터페이스를 만들수 있도록
디폴트 메서드를 추가.
- 특정 프로그램을 구현하는 데 도움을 주는 기능이 아니라 미래에 프로그램이
쉽게 변화할 수 있는 환경을 제공하는 기능.
- 구현 클래스에서 구현하지 않아도 되는 메서드를 인터페이스가 포함할 수 있는 기능도 제공.
- 메서드 바디는 클래스 구현이 아니라 인터페이스의 일부로 포함.
> 그래서 이를 디폴트 메서드 라고 부름.
- 디폴트 메서드를 이용하면 기존의 코드를 건드리지 않고
원래의 인터페이스 설계를 자유롭게 확장 가능.
- 자바 8에서는 인터페이스 규격명세에 default 라는 새로운 키워드를 지원.
5. 함수형 프로그램에서 가져온 다른 유용한 아이디어
- 자바에 포함된 함수형 프로그래밍의 핵심적 두 아이디어는 아래와 같음.
> 메서드와 람다를 일급값으로 사용하는 것
> 가변 공유 상태가 없는 병렬 실행을 이용하여 효율적이고 안전하게
함수나 메서드를 호출 할 수 있다는 것.
- null회피 기법
> NullPointer 예외를 피할 수 있도록 도와주는 Optional<T> 클래스 제공.
> Optional<T>는 값을 갖거나 갖지 않을 수 있는 컨테이너 객체.
> OPtional<T>는 값이 없는 상황을 어떻게 처리할지 명시적으로 구현하는 메서드를 포함.
> 즉, 형식 시스템을 이용해서 어떤 변수에 값이 없을 때 어떻게 처리할지 명시할 수 있음.
- 패턴 매칭 기법
> switch를 확장한 것으로 데이터 형식 분류와 분석을 한번에 수행 가능.
6. 요약
- 언어 생태계의 모든 언어는 변화해서 살아남거나 그대로 머물면서 사라지게 되는 상황에 놓임.
- 자바 8은 프로그램을 더 효과적이고 간결하게 구현할 수 있는 새로운 개념과 기능을 제공.
- 기존 자바 프로그래밍 기법은 멀티코어 프로세서를 온전히 활용하기 어려움.
- 함수는 일급값. 메서드를 어떻게 함수형값으로 넘겨주는지,
익명함수(람다)를 어떻게 구현 하는지 기억해야 함.
- 자바 8의 스트림 개념 중 일부는 컬렉션에서 가져온 것.
스트림과 컬렉션을 적절하게 활용하면 스트림의 인수를 병렬로 처리할 수 있으며
더 가독성 좋은 코드 구현 가능.
- 인터페이스에서 디폴트 메서드를 이용하면 메서드 바디를 제공할 수 있으므로
인터페이스를 구현하는 다른 클래스에서 해당 메서드를 구현하지 않아도 됨.
- 함수형 프로그래밍에서 null 처리 방법과 패턴 매칭 활용 등 흥미로운 기법을 발견.
'Java8 > Java 8 in Action' 카테고리의 다른 글
스트림 활용 (0) | 2017.06.26 |
---|---|
스트림 소개 (0) | 2017.06.16 |
람다 표현식 (0) | 2017.06.15 |
동작 파라미터화 예제 소스 (0) | 2017.06.13 |
자바8 동작 파라미터화 코드 전달하기 (0) | 2017.06.13 |