728x90
자바 역사를 통틀어 가장 큰 변화가 자바 8에서 일어났다.
1.1 역사의 흐름은 무엇인가?
자바 8
을 이용하면 자연어에 더 가깝게 간단한 방식으로 코드를 구현할 수 있다.- 지금까지의 대부분의 자바 프로그램은 코어 중 하나만을 사용했다.
- 나머지 코어는 유휴 idle 상태로 두거나, 운영체제나 바이러스 검사 프로그램과 프로세스 파워를 나눠서 사용
자바 8
등장 이전 : 나머지 코어 활용 → 스레드- 스레드 사용은 관리가 어렵고 많은 문제가 발생할 수 있음
- 자바 1.0 : 스레드, 락, 메모리 모델 지원
- 자바 5 : 스레드 풀(thread pool), 병렬 실행 컬렉션(concurrent collection)
- 자바 7 : 포크/조인 프레임워크
- 자바 8 : 스트림 API, 동작 파라미터화, 인터페이스의 디폴트 메서드
- 자바 9 : 리액티브 프로그래밍(RxJava)
자바 8
- 간결한 코드
- 멀티코어 프로세서의 쉬운 활용
- 스트림
- DB 쿼리에서 고수준 언어로 동작 표현 → 자바에서 최적의 저수준 실행 방법 선택 후 동작
synchronized
를 사용하지 않아도 된다.- High Cost : 멀티 코어 CPU에서 각 코어는 별도 캐시를 두고 있는 데, 락을 사용하면 캐시가 동기화되어야함
⇒ 캐시 일관성 프로토콜 인터코어 통신(cache-coherency-protocol intercore communication) 발생
- High Cost : 멀티 코어 CPU에서 각 코어는 별도 캐시를 두고 있는 데, 락을 사용하면 캐시가 동기화되어야함
- ⭐ 함수형 프로그래밍(functional-style programming)
1.2 왜 아직도 자바는 변화하는가?
- 완벽한 프로그래밍 언어
- 시공을 초월하는 완벽한 언어를 원하지만 현실적으로 그런 언어는 존재하지 않다.
- C, C++
- 프로그래밍 안전성 부족 But, 작은 런타임 “Foot Print”
- 👣 *Foot Print ?* → 하드웨어나 소프트웨어 단위가 차지하고 있는 공간의 크기 → 프로그램 실행 중에 사용하거나 참조하는 메인 메모리의 총량
- 낮은 안정성 → 프로그램이 예기치 않게 종료되거나 바이러스 침투 가능
- 자바의 위치
- 잘 설계된 객체 지향 언어로 시작
- 코드를 JVM 바이트 코드로 컴파일 하는 특징 → 모든 브라우저에서 JVM 지원
- 인터넷 애플릿 프로그램의 주요 언어
- 객체 지향
- 캡슐화
- 엔지니어링적인 문제가 훨씬 적음
- ‘모든 것은 객체다’로 대입
- 일단 만들면 모든 곳에서 실행 가능(write-once run-anywhere)
- 캡슐화
- 초기에는 C, C++에 비해 추가적으로 드는 비용 때문에 자바에 대한 반감 존재
- But, 하드웨어의 발전으로 실행시간 크게 지장 ❌
자바 8
에서 제공하는 기능의 모태 프로그래밍 개념들- 더 다양한 프로그래밍 도구
- 다양한 프로그래밍 문제를 더 빠르고 정확하며 쉽게 유지보수의 장점 제공
1.2.2 스트림 처리
- 스트림 처리(stream processing)
- 스트림 : 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임
- 유닉스, 리눅스의 많은 프로그램 : 표준 입력에서 데이터 Read → 표준 출력으로 데이터 Write
- e.g. Unix Command
$ cat file1 file2 | tr "[A-Z]" "[a-z]" | sort | tail -3
유닉스에서는 여러 명령을 병렬로 실행
- 스트림 API
- 어떤 항목을 연속으로 제공하는 어떤 기능
- Before : 한 번에 한 항목 처리
- After(
자바 8
) : 고수준 추상화 → 일련의 스트림으로 만들어서 처리
스트림 파이프라인을 이용하여 입력 부분을 여러 CPU 코어에 쉽게 할당
1.2.3. 동작 파라미터화로 메서드에 코드 전달하기
- 동작 파라미터화(behavior parameterization)
- 코드 일부를 API로 전달하는 기능 (= 메서드를 다른 메서드의 인수로 넘겨주는 기능)
1.2.4. 병렬성과 공유 가변 데이터
‘병렬성을 공짜로 얻을 수 있다’
- 스트림 메서드로 전달하는 코드의 동작 방식 변경
- 스트림 메서드로 전달하는 코드는 다른 코드와 동시에 실행하더라도 안전하게 실행될 수 있어야 한다.
- 안전하게 실행?
- 공유된 가변 데이터(shared mutable data)에 접근 하지 않아야한다.
- (순수 함수, 부작용 없는 함수, 상태 없는 함수)
- 공유된 변수를 동시에 바꾸려고 할 때
synchronized
: 공유된 가변 데이터를 보호하는 규칙 생성- But, synchronized 는 시스템에 악영향을 미친다.
자바 8
스트림을 이용해서 병렬성 활용 가능
1.2.5. 자바가 진화해야 하는 이유
자바 8
의 큰 변화 : 고전적인 객체 지향 → 함수형 프로그래밍
✨ 언어는 하드웨어나 프로그래머 기대의 변화에 부응하는 방향으로 변화해야 한다.
1.3 자바 함수
- 함수 = (정적) 메서드
자바 8
에서는 함수를 값 처럼 취급- 자바 프로그램에서 조작할 수 있는 값
- 기본값 (e.g.
int
,boolean
) - 객체(객체의 참조) (e.g.
new
)
- 기본값 (e.g.
✨ 프로그래밍 언어의 핵심 : 값을 바꾸는 것
→ 일급값(first class : 퍼스트 클래스)
- 런타임 시, 메서드 전달하면 프로그래밍에 유용하게 활용 가능
1.3.1 메서드와 람다를 일급 시민으로
- 메서드 참조(method reference)
e.g.
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isHidden();
}
});
- FileFilter로 isHidden을 감싼 후 인스턴스화
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
- 메서드 참조(이 메서드를 값으로 사용하라)를 이용해, listFiles에 직접 전달
- 기존에 비해 문제 자체를 더 직접적으로 설명
- 람다 : 익명 함수
- 람다를 포함하여 함수도 값으로 취급 가능
- 숨겨진 파일 필터링 방식
1.3.2 코드 넘겨주기
- e.g. Apple 클래스와 getColor 메서드 존재
<사과 무게 | 색상으로 필터링>
// 녹색 사과 필터링 메서드
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple: inventory) {
if (GREEN.equals(apple.getColor())) {
result.add(apple);
}
} return result;
}
// 150그램 이상 사과 필터링 메서드
public static List<Apple> filterHeavyApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple: inventory) {
if (apple.getWeight() > 150) {
result.add(apple);
}
} return result;
}
- 중복 코드 (copy & paste) 개선
public static boolean isGreenApple(Apple apple) {
return GREEN.equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple) {
return apple.getWeight() > 150;
}
public interface Predicate<T>{
boolean test(T t);
}
static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p){
List<Apple> result new ArrayList<>();
for (Apple apple: inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
filterApples(inventory, Apple::isGreenApple);
filterApples(inventory, Apple::isHeavyApple);
- 프레디케이트(Predicate) : boolean 값을 리턴하는 함수
1.3.3 메서드 전달에서 람다로
- 한 두번만 사용할 메서드 정의 → 비효율적
- 따로 정의를 구현하지 않고 람다를 이용하여 구현한다.
filterApples(inventory, (Apple a) -> GREEN.equals(a.getColor()));
filterApples(inventory, (Apple a) -> a.getWeight() > 150);
filterApples(inventory, (Apple a) -> a.getWeight() < 80 || RED.equals(a.getColor()));
- But, 람다가 몇 줄 이상으로 길어지게 된다면 메서드를 정의하고 메서드 참조를 활용하는 게 바람직하다.
코드의 명확성이 우선
728x90
'📖 Book' 카테고리의 다른 글
[모던 자바 인 액션] 2. 동작 파라미터화 코드 전달하기 (53) | 2024.01.29 |
---|---|
[헤드 퍼스트 디자인 패턴] 1. 전략 패턴 (0) | 2024.01.15 |
[구글 엔지니어는 이렇게 일한다] Overview (0) | 2022.08.08 |