SlideShare a Scribd company logo
1 of 12
Download to read offline
TECHNOLOGY & 
DEVELOPER 
68_ Java8&Beyond
Java8 소개 
지금으로부터 약 20년 전인 1994년, Sun의 James Gosling 박사는 이후에 프로그래밍 세계를 완벽히 바꿔 
놓은 ‘Oak’ 라고 하는 언어를 개발하게 된다. 이것이 바로 현재 전세계 약 900만 이상의 개발자들이 사용하 
고 있는 Java의 시초이다. Java는 1996년 1.0 버전이 처음 세상에 나왔고, 2014년 3월 그 여덟 번째 버전인 
Java SE8 이 세상에 나올 채비를 갖추었다. Java 가 오늘에 이르기 까지 겪었던 변화들을 살펴보면 먼저 플 
랫폼이 모바일, 엔터프라이즈로 세분화 되었고, RMI, Native IO(NIO), XML 파서, Concurrent Utility 등 수 
많은 새로운 기능들이 추가 되었으며, Generic 및 Annotation 등의 지원이 추가 되었고, 하드웨어적으로 
는 Embedded CPU까지 지원함으로써 엔터프라이즈 시장을 넘어 모바일, Internet of Things 세계에서도 
기존 개발자들이 그들의 역량을 그대로 활용할 수 있도록 발전해 왔다. 이러한 진보와 더불어 Java의 오픈 
소스 화도 빼놓고 얘기할 수 없을 것 같다. 2006년 JavaOne에서 발표된 오픈 소스화 발표 이후 그 첫 결과 
물로 Java SE7 의 Reference Implementation인 OpenJDK가 발표 되었다. 이후 OpenJDK는 오픈 소스 
커뮤니티 및 개발자들의 도움으로 빠르게 발전해 왔다. OpenJDK의 대표적인 성공사례로 Taobao(중국의 
e-commerce 회사)가 손꼽히고 있는데, 그들의 환경에서 성능 최적화된 Customized JVM을 약 1만개 이 
상의 인스턴스에서 운영하고 있다고 한다(JavaOne 2012년 발표 참조). 
이렇게 뒤돌아보면 열거할 수 없을 정도로 많은 변화들을 겪어 왔지만 그 중에서도 Java8은 이전에 그 어느 
TECHNOLOGY & DEVELOPER 
Java8&Beyond 
저자 - 이창재 컨설턴트, Oracle APAC STAr Team, Senior Architect 
2014년 Big Trend 중 하나는 Internet of Things, 일명 IOT라고도 불리며 모든 사물이 인터넷에 
연결되어 동작하는 것을 의미한다. 이전에는 Embedded 기기로써 인터넷에 연결되지 않고 
개별기기가 동작하는 형태였고, 보통 C나 어셈블리를 통해서 프로그래밍 해왔지만 2014년에는 
C나 어셈블리 같은 언어를 따로 배우지 않고도 Java 개발자들이 이러한 Embedded 기기를 위해 
프로그래밍하고 인터넷에 연결하여 사물 인터넷을 구성할 수 있게 되었다. 
이제 Java는 하나의 플랫폼으로 진화하고 있다. Java라는 언어만 실행하는 것이 아니라 다른 여러 
함수형 언어까지 Java Virtual Machine의 그릇에 담고, 서버 뿐만 아니라 Embedded 디바이스 같은 
소형 기기에서도 동일한 개발 스킬을 활용할 수 있는 시대가 오고 있다. 2014년 3월에 출시될 Java 8은 
이렇듯 언어적인 진화와 더불어 대대적으로 플랫폼적인 진화가 예고되어 있다. 본고에서는 Java 8에 
핵심 변화들에 대해서 알아보고자 한다. 
Technology & Developer Java8&Beyond ORACLE KOREA MAGAZINE Spring 2014 68
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
69 
Spring 2014 
버전들 보다 더 많은 변화가 예고되어 있다. Interface에 default 메소드, static 메소드 사용이 가능해진 것이 언어 측면에서의 대표적인 변화라고 볼 수 있다. 그리고 특히 이번 버전에서 가장 중요한 기능으로 평가 받고 있는 Lambda는 기존과는 다른 새로운 프로그래밍 방식을 채용하기를 개발자들에게 요구하고 있다. 참고로 Java는 전세계에서 가장 많이 쓰이는 프로그래밍 언어(Github top10 2013년 기준) 중에서 가장 늦게 Lambda expression을 채용한 언어가 되었다. 새 버전에는 이 Lambda를 이용해서 Collection을 좀 더 효율적으로 또한 지금까지 지속적으로 문제가 제기 되어왔던 Time 및 Date 관련 API가 마침내 완전히 새롭게 개선되었다. 성능 및 개발 생산성 측면에서 그동안 어쩔 수 없이 Joda Time이나 Apache commons 라이브러리들을 사용해 왔던 애플리케이션 개발자들에게는 아주 기쁜 소식이 될 것이다. 플랫폼 측면에서는Java7의 invokedynamic의 결실로 JVM 기반에 javascript 엔진 Nashorn 등이 소개 되었다. 그 밖에도 부족한 지면으로 다룰 수는 없지만 NIO2나 Concurrent API 등에 여러 가지 개선이 이루어 졌고 Optional 타입도 소개되었다. 본고는 지면 관계상 가장 주목해야 할 변화들에 초점을 맞추어 설명하였다. 
<Example Code 1> 
@FunctionalInterface 
public interface Comparator<T> { 
int compare(T o1, T o2); // 1 
boolean equals(Object obj); 
default Comparator<T> reversed() { //2 
return Collections.reverseOrder(this); 
} 
....... 생략 
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) { //3 
Objects.requireNonNull(keyExtractor); 
return (Comparator<T> & Serializable) 
(c1, c2) -> 
Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2)); 
} 
} 
Interface 향상 
위의 <Example Code 1>은 Java8의 Comparator의 소스를 가져 온 부분이다. 평이한 Interface처럼 보이지만 //2, //3 번을 눈여겨보기 바란다. 먼저 default 메소드에 대해서 알아보자. 이전 버전까지 Interface에 abstract 메소드들은 반드시 클래스에서 해당 메소드들을 구현해 주어야 했다. 어떠한 이유에서든지
Interface에 새로운 메소드들이 추가 되는 경우, 소스 코드들을 고쳐줘야 했고(해당 메소드들을 구현), 이로 인해 바이너리 호환성에 이슈가 생길 수밖에 없었다. 이러한 이유로 default 메소드라는 개념이 생기게 되었다. Lambda(이후에 설명할)를 Collection API에 지원하려고 하면서 발생했던 문제를 예를 들어 설명해 보면, Collection Interface에 확장을 위해서 새로운 abstract 메소드가 지정 되는 경우 이를 implement하는 ArrayList, Vector 등 모든 클래스들이 변경되어야 한다. 새롭게 확장할 메소드들을 default 메소드로 지정하는 경우에는 그러한 작업이 필요 없어지는 것이다. 즉 default 메소드는 이를 구현하는 모든 클래스들이 동일한 기능을 사용할 수 있도록 하는 동시에, 인터페이스에 변경이 생기더라도 바이너리 호환성을 유지할 수 있는 방법을 제공해 준다. 
static 메소드의 허용도 눈 여겨 볼만 하다. 기존에는 abstact 메소드 혹은 필드 변수(암시적으로 static final 로 지정됨)만이 지정 가능했다면 이제는 //3처럼 static 메소드를 직접 Interface 안에서 구현 가능하다. 
Lambda Expression 
Lambda는 Java8의 신기능 중에서도 가장 많은 스포트라이트를 받고 있는 기능이다. Lambda의 이해를 위해서 다음의 익명 클래스(anonymous class)의 예를 살펴보자. 
<Example Code 2> 
new Thread(new Runnable() { 
public void run() { 
System.out.println(“Thread run!!”); 
} 
}).run(); 
Runnable이나 ActionListener 혹은 Comparator처럼 오직 하나의 메소드만을 가진 인터페이스를 SAM(Single Abstract Method Type)이라고 한다. Lambda는 이렇게 오직 하나의 메소드만을 가진 인터페이스를 Functional Interface라고 부른다. <Example Code 1>의 //3에 Comprator가 대표적으로 @ FunctionalInterface annotation을 구현한 인터페이스이다. 코드를 보면 Function Interface의 규칙을 Comparator가 지키고 있는 것 같아 보이지 않는다. 코드는 compareTo()와 equals(),두 메소드가 abstract 메소드로 지정되어 있는데 어떻게 annotation이 허용될까? 그 이유는 바로 equals가 Object의 public 메소드이기 때문이다. Java 언어 스펙에는 모든 Interface는 Object의 public 메소드를 정의하도록 되어 있다. 이러한 이유로 toString이나 equals같은 메소드들은 Functional Interface의 규칙에 위배 되지 않는다. 
Lambda 표현식의 예를 구체적으로 알아보자. 위의 Runnable 코드를 Lambda로 구현하면 다음과 같이 한 줄로 표현 된다. 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
70 
Spring 2014
<Example Code 3> 
Runnable r = () -> { System.out.println(“Thread run!!”); } 
기본적으로 Lambda 표현식은: (변수 목록) -> Body 로 표현된다. <Example Code 3>에서 보듯이 run 메소드의 경우 변수를 받지 않으므로 ( )으로 표현 된다. 아래의 예도 같이 살펴보자. 
(int x, int y) -> x + y 
(String s) -> { System.out.println(s); } 
Java8은 Lambda Expression을 지원하는 java.util.function 패키지가 추가 되었다. 
지면 관계상 Predicate와 Consumer의 예만 살펴보자. Predicate의 예제 먼저 살펴보면, p.getAge() >=16 처럼 조건 자체를 메소드의 변수로 전달할 수 있다. 
<Example Code 4> 
Predicate<Person> allDrivers = p -> p.getAge() >= 16; 
public void phoneContacts(List<Person> pl, Predicate<Person> pred){ 
for(Person p:pl){ 
if (pred.test(p)){ 
roboCall(p); 
} 
} 
} 
Function의 코드 예제도 살펴보자. 아래의 <Example Code 5>은 westernStype이라고 하는 Function 자체를 전달해서 Person 오브젝트를 Western 스타일의 이름으로 출력해 주는 예제이다. 
java.util.function.Predicate 
변수로 전달된 오브젝트의 속성 
java.util.function.Consumer 
변수로 전달된 오브젝트에 수행할 액션. 리턴 값 없음 
java.util.function.Function<T,U> 
T를 U로 변경 
java.util.function.Supplier<T> 
<T>를 만드는 인스턴스(대표적으로 Factory 클래스) 
java.util.function.UnaryOperator 
단항(Unary) 연산 
java.util.function.BinaryOperator<T,T> 
복수항(Binary) 연산 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
71 
Spring 2014
<Example Code 5> 
public String printCustom(Function <Person, String> f){ return f.apply(this); } 
Function<Person, String> westernStyle = p -> { 
return "nName: " + p.getGivenName() + " " + p.getSurName() + "n" +"Age: " + p.getAge() + " " + "Gender: " + p.getGender() + "n" +"EMail: " + p.getEmail() + "n" + "Phone: " + p.getPhone() + "n" + "Address: " + p.getAddress(); }; 
System.out.println("n===Western List==="); 
for (Person person:list1){ 
System.out.println(person.printCustom(westernStyle)); 
} 
<Example Code 5>에서처럼 Lambda는 기능 혹은 코드 자체를 다른 메소드로 전달할 수 있는 기능을 제공함으로써 이전 보다 더 간결하고 유연한 프로그래밍이 가능해졌다. 
Stream API 
이전 버전에서 Collection은 항상 Iterator를 통해 for 혹은 while 구문을 사용하여 접근했었다. Java8 에서는 java.util.stream 패키지와 Lambda를 활용하여 이전 보다 훨씬 세련되고 향상된 방법으로 Collection을 처리할 수 있게 되었다. 
stream은 순차(sequential), 그리고 병렬(parallel) 두 종류로 존재한다. 순차 스트림의 경우는 싱글 쓰레드로 순차대로 처리될 것이고 병렬 스트림은 stream이 Fork/Join 프레임워크로 구현된 메소드에 의해서 병렬로 처리된다. 코드 예를 살펴보자. 
<Example Code 6> 
int totalCountOfOrder = orderList.stream() 
.filter(b -> b.getProduct() == "iPhone") 
.map(b -> b.getAmount()) 
.sum(); 
<Example Code 6>을 보자. filter의 경우 Predicate 형을 받아서 처리하여 Stream(T) 형으로 돌려주게 되고, 이를 map이 Function을 매개변수로 받아서 처리한 후에 타겟 타입이 int이므로 IntStream으로 돌려주면 sum이 이를 합해서 최종 결과를 도출해 낸다. 위에 예제에서 map 이나 filter 같은 연산자들은 임시 연산자(Intermediate Operator)라고 불리며 작업 결과를 뒤로 전달해 주는 역할을 한다. 앞에 sum이나 forEach, count 등은 종료 연산자(Terminal Operator)라 불리며 말 그대로 최종적으로 Stream을 처리하는 역할을 한다. parallelStream의 예도 살펴보자. 다음의 코드는 모든 파일럿들의 나이(getAge)의 평균 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
72 
Spring 2014
(average)을 병렬로 구하는 예이다. 
<Example Code 7> 
OptionalDouble averageAge = pl 
.parallelStream() 
.filter(search.getCriteria("allPilots")) 
.mapToDouble(p -> p.getAge()) 
.average(); 
Stream의 사용에 있어서 장단점을 살펴 보면 먼저 장점으로 Laziness를 들 수 있다. 즉 Collection에 iteration 처리를 자바에게 맡겨둠으로써 JVM 이 코드에 대한 처리를 최적화할 수 있는 기회를 제공한다. 단점 및 주의해야 할 사항으로 stream 은 재사용이 불가능 하다는 것이다. 한번 사용된 stream은 재사용이 불가능하며, 필요에 따라서 새롭게 만들어져야 한다. 
Time And Date API 
프로그래밍을 하면서 가장 흔하게 접하게 되는 요구사항 중에서 날짜 및 시간의 처리가 빠질 수가 없을 것이다. Java에는 1.0부터 java.util.Calendar, java.util.Date 등의 API를 제공해 왔다. 그렇다면 어떠한 문제가 있었길래 그동안 개발자 커뮤니티에서 지속적으로 개선에 대해 요구해 왔고 어떠한 식으로 개선이 되었는지를 살펴보자. 가장 잘 알려진 문제점부터 나열해 보면: 
1. 년은 1900년부터 시작한다. 1900년도 이전에 대한 처리는 workaround가 필요. 
2. 월이 1부터가 아닌 0부터 시작한다. 그러므로 12월은 실제로 숫자 11이다. 
3. Mutable하므로 thread safe하지 않다. 
4. Performance 문제 
이러한 문제들 외에도 직관적이지 않고 각각의 처리를 위해서 추가적인 클래스들이 필요(예를 들어 SimpleDateFormat 같은)한 것 등이 문제점으로 지적되어 왔다. Java8에 새롭게 추가된 Time And Date API는 Joda Time을 만든 Stephane Coleburne가 리딩하고 있는 JSR-310을 기반으로 하고 있다. 새롭게 만들어진 Time And Date API는 java.util.Date, java.util.Calendar, java.util.TimeZone, java.util. DateFormat이 4개를 전부 대체하고 있다. 
새롭게 추가된 java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time. ZonedDateTime 등이 이를 대체하게 된다. LocalDate의 경우 년-월-일, LocalTime은 시-분-초-나노초, LocalDateTime은 년-월-일-시-분-초를 내부적으로 저장한다. 각각의 API 에 대한 사용 예는 <Example Code 7>을 살펴보자. 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
73 
Spring 2014
<Example Code 7> 
LocalDate currentDate = LocalDate.now(); 
boolean isLeapYear = currentDate.isLeapYear(); 
LocalDate date = LocalDate.of(2014, Month.FEBRUARY, 12); 
LocalTime currentTime = LocalTime.now(); 
LocalDateTime currentDateTime = LocalDateTime.now(); 
currentDateTime = LocalDateTime.of(2014, 2, 21, 13, 40); 
date = currentDateTime.plusMonths(1).minusDays(3); 
시간 및 날짜의 조정은 plus/minus/with 등 알기 쉬운 명칭의 API 로 변경 되었다. TimeZone 지원은 ZonedDateTime을 통해 이루어지며 내부적으로는 LocalDateTime, ZoneId, ZoneOffset이 3가지가 저장된다. ZoneId의 경우 “Europe/London”, “Asia/Seoul” 등으로 표현 되며 ZoneOffset은 -18:00부터 +18:00의 범위로 표현된다. 한국의 경우는 +09:00으로 표현된다. 이외에도 java.time에는 Instant, Amount, Duration, Period 등의 클래스들이 추가 되었다. 
Type Annotation 
Java8에 추가된 Type Annotation은 새롭게 type 시스템에 추가된 기능으로, 어떠한 type, 예를 들어 새로운 operator나 implements구문, throws구문 등에 추가할 수 있는 annotation이다. 
<Example Code 8> 
@NotNull String str1 = ... 
@Email String str2 = ... 
@NotNull @NotBlank String str3 = ... 
Map.@NonNull Entry = ... 
myString = (@NonNull String) myObject; 
void monitorTemperature() throws @Critical TemperatureException { ... } 
void authenticate() throws @Fatal @Logged AccessDeniedException { ... } 
<Example Code 8>에서 보듯이 @NotNull @Email 등의 type annotation을 통해서 해당 변수에 대한 type을 지정해 줄 수 있다. 또한 throws 같은 구문에도 annotation을 지정하는 것이 가능하다. 
이렇게 언어적으로 상당히 유용한 기능이 추가 되었지만, 한 가지 유의할 점은 현재 자바 컴파일러가 지정된 type에 대한 사용을 강제하지 않는 다는 것이다. 즉 annotation 사용이 가능하고 컴파일이 가능하지만, 실 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
74 
Spring 2014
제로 지정된 type을 준수하는지에 대한 체크는 IDE 나 별도의 Framework(Checker Framework)을 이용해야 한다는 것이다. 
Repeating Annotation 
기존에는 동일한 Annotation의 중복 선언은 허용되지 않았다. Java8부터는 동일한 Annotation의 중복 선언이 허용 된다. java.lang.annotation.Repeatable이 새로 소개되었다. 다음의 <Example Code 9>는 주기적으로 어떤 작업을 수행하는 Scheduler에 복수개의 Schedule을 annotation을 이용해서 지정한 예이다. 
<Example Code 9> 
@Schedule(dayOfMonth="last") 
@Schedule(dayOfWeek="Fri", hour="23") 
public void doPeriodicCleanup() { ... } 
JDK Convergence 
현재 Oracle은 Hotspot과 JRockit JVM 두 가지를 고객에게 제공하고 있다. JRockit JVM 은 BEA에서 Oracle로 넘어온 JVM이고 특히 JRockit Realtime(JRRT)는 Latency가 중요한 고객들에게 Deterministic GC를 제공함으로써 안정적으로 시스템을 운영할 수 있는 장점을 제공해 왔다. Oracle은 JRockit이 가진 강점을 Hotspot에 접목 시켜서 하나의 JVM으로 만들기로 결정을 내렸고, 이러한 Convergence의 결과물이 Java7 Update 40에서 처음으로 소개 되었다. 바로 Java Mission Control과 Flight Recorder가 그것인데, JMC는 <그림1>과 같이 현재 JVM에서 벌어지는 상황을 GUI로 한눈에 확인할 수 있는 툴이고, Flight Recorder는 실제 JVM이 실행될 때의 모든 Metric을 저장해서 마치 비행기의 블랙박스처럼 나중에 돌려 보고 문제를 파악할 수 있는 기능을 제공한다. 
JDK Convergence는 Java8에서도 계속되는데 대표적으로 Permanent 영역이 사라졌다. Perm 영역에 저장되었던 정보들 중에서 String Constant Pool은 Heap 영역으로 이동 되었고, 기타 클래스 메타데이타 정보 같은 것들은 Metaspace라고 하는 Native Memory 영역으로 이동 되었다. 이 영역은 MaxMetaspaceSize 옵션을 통해서 사이즈를 지정해 줄 수 있으며, 이 영역도 Garbage 
<그림 1> Java Mission Control 화면 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
75 
Spring 2014
Collection 이라는 개념이 존재한다. 
이후 JDK8 Update로써 JRockit Realtime의 Deterministic GC 기능과 비슷한 Deterministic G1 기능이 제공될 예정이다. 
Compact Profile 
Oracle은 JavaOne에서 Java ME와 SE의 convergence에 대해서 소개한 바 있다. Convergence 작업에 일환으로 Java8부터는 Java ME/CDC가 Java SE Embedded에 의해 대체된다. 이 Java SE Embedded에 근간이 되는 것이 바로 Compact Profile이다. Raspberry Pi나 PandaBoard 등이 대표적인 타겟 플랫폼이 될 것이다. 
정식 버전 출시 전이라 얼마나 ‘Compact’ 한지 정확한 자료를 제공하긴 어렵지만 Early Access 버전을 테스트한 자료에 따르면 ARMv5/Linux 기준으로 Compact 1은 대략 14MB, Compact 2는 대략 18MB, Compact 3는 21MB 정도의 footprint를 나타내고 있다. 
Project Nashorn 
Javascript를 JVM 에서 동작시킨다는 아이디어는 꽤 오래 전으로 거슬러 올라간다. Wikipedia에 따르면 1997년 Netscape가 100% Java 기반에 브라우저를 만들려고 계획하면서부터 시작되었다고 한다. 그 당시에 프로젝트 이름은 ‘Rhino’라고 하며(이 이름도 O’Reilly의 Javascript책 표지에서부터 비롯되었다고 한다), ‘Nashorn’은 바로 Rhino의 독일어라고 한다. Rhino는 ECMAScript 5.1 표준을 완벽히 구현하고 있으며 Java SE 8 및 ME 8에 모두 소개될 예정이다. 
Nashorn에 대해서 이야기하기 위해서 먼저 JDK 7에 새롭게 소개된 invokedynamic을 살펴 보자. 앞에서 소개한 Lambda는 내부적으로 이 invokedynamic을 활용한다. invokedynamic은 JVM 의 플랫폼화를 이야기하기 위한 필수적인 개념이다. 자바는 언어적으로 static type 언어라고 불리며 이것은 컴파일 타임에서 이미 멤버 변수들이나 함수의 변수들의 타입이 반드시 명시적으로 지정되어야 함을 의미한다. 그에 반해 Ruby 나 javscript 들은 이른바 ‘duck-typing’ 이라고 하는 타입 시스템을 채용함으로써 컴파일타임에서의 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
76 
Spring 2014 
<그림 2> shell scripting 
<그림 3> Shelling Script 실행
type을 강제 하지 않는다. invokedynamic은 이러한 duck-typing을 JVM 레벨에서 기본적으로 지원하면서 Java 외에 다른 언어들이 JVM이라는 플랫폼 위에서 최적화된 방식으로 실행될 수 있는 토대를 제공해 준다. 
Java8에는 jjs라고 하는 커맨드라인 툴을 이용해서 Nashorn 엔진을 호출할 수 있다. <그림 2, 3>의 예에서 보듯이 자바스크립트 안에서 직접 Java Class 들을 생성하고 호출할 수 있다. 또한 JavaFX 애플리케이션을 실행할 수도 있다. 
맺음말 
Java8에 새롭게 소개된 기능들에 대해서 간략히 살펴보았다. 소개한 대로 많은 변화들이 이루어 졌으며 또한 그 동안 개발자들에게 pain point였던 부분들이 상당 부분 개선되었음을 알 수 있다. 본래부터 Java는 2년 주기의 메이저 업데이트를 통해서 빠르게 새로운 기술들이 채용되고 소개되어 왔다. 물론 2006년 Java6 에서 2011년 Java7으로 이 사이클이 깨어지긴 했지만, 내부적인 이유(Sun Microsystems의 합병)와 외부적인 이유(OpenJDK)의 복합적인 작용이 컸었던 만큼 앞으로는 다시 2년 주기로 새로운 버전이 나올 예정이다. 보안 이슈로 1년 미루어진 Java8 버전부터 다시 본래의 주기로 돌아오게 되면 앞으로는 이러한 변화들을 체감 속도보다 더 빠르게 그리고 지속적으로 체감할 것으로 예상 된다. 
이 글을 읽고 난 후에 독자들이 가질 가장 큰 의문은 “새로운 기능이 좋아 보이긴 하는데 Java8을 당장 채용해도 될까?”일 것이다. 여기에 대한 대답으로 필자는 손자병법을 인용하면서 글을 마무리 하고자 한다. 손자병법에는 應形無窮(응형무궁)이란 말이 있다. “끊임없는 변화에 준비하고 대응하라”라는 뜻이다. Java7, 8에서의 변화는 Java가 앞으로 새로운 10년을 나아가는 데에 있어서 디딤돌이 될 것임을 개인적으로 예상하는 바이고, 이 끊임없는 변화에 준비하고 대응하기 위해서, 그러므로 가장 먼저 해야 할 일이 바로 Java8을 채용하는 일일 것이다. Java8 버전은 이 글을 작성하고 있는 2014년 2월 현재 https://jdk8.java.net/ download.html에서 다운로드 받을 수 있다. 
ORACLE KOREA MAGAZINE 
Technology & Developer 
Java8&Beyond 
77 
Spring 2014
Copyright © 2009, Oracle. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. oracle.com/goto/industries또는 080.2194.114로 문의하세요. #1 Development PlatformComputers, Printers, Routers, BlackBerry Smartphones, Cell Phones, Kindle E-Readers, Parking Meters, Vehicle Diagnostic Systems, On-Board Computer Systems, Smart Grid Meters, Lottery Systems, Airplane Systems, ATMs, Government IDs, Public Transportation Passes, Credit Cards, VoIP Phones, Livescribe Smartpens, MRIs, CT Scanners, Robots, Home Security Systems, TVs, Cable Boxes, PlayStation Consoles, Blu-ray Disc Players… 30억개의디바이스에서자바를 운영합니다PRODUCTION

More Related Content

What's hot

나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선daewon jeong
 
자바에서 null을 안전하게 다루는 방법
자바에서 null을 안전하게 다루는 방법자바에서 null을 안전하게 다루는 방법
자바에서 null을 안전하게 다루는 방법Sungchul Park
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개Sungchul Park
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발NAVER D2
 
Function & Closure about Swift
Function & Closure about Swift Function & Closure about Swift
Function & Closure about Swift KimDaeho
 
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Why what how kotlin
Why what how kotlinWhy what how kotlin
Why what how kotlinSewonKo
 
안드로이드 개발자에 필요한 오픈소스이야기
안드로이드 개발자에 필요한 오픈소스이야기안드로이드 개발자에 필요한 오픈소스이야기
안드로이드 개발자에 필요한 오픈소스이야기YoungSu Son
 
[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)
[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)
[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)Sang Don Kim
 
델파이와 유니코드
델파이와 유니코드델파이와 유니코드
델파이와 유니코드Devgear
 
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로Oracle Korea
 
Protocol Oriented Programming in Swift
Protocol Oriented Programming in SwiftProtocol Oriented Programming in Swift
Protocol Oriented Programming in SwiftSeongGyu Jo
 

What's hot (20)

나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
 
6 swift 고급함수
6 swift 고급함수6 swift 고급함수
6 swift 고급함수
 
Java8 람다
Java8 람다Java8 람다
Java8 람다
 
C++에서 Objective-C까지
C++에서 Objective-C까지C++에서 Objective-C까지
C++에서 Objective-C까지
 
자바에서 null을 안전하게 다루는 방법
자바에서 null을 안전하게 다루는 방법자바에서 null을 안전하게 다루는 방법
자바에서 null을 안전하게 다루는 방법
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개
 
JDK 변천사
JDK 변천사JDK 변천사
JDK 변천사
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발
 
Function & Closure about Swift
Function & Closure about Swift Function & Closure about Swift
Function & Closure about Swift
 
5 swift 기초함수
5 swift 기초함수5 swift 기초함수
5 swift 기초함수
 
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
스프링프레임워크 & 마이바티스 무.료 강의자료 제공 (Spring IoC & DI)_ 구로자바학원/구로오라클학원/구로IT학원
 
5.Spring IoC&DI(DI와 관련된 어노테이션)
5.Spring IoC&DI(DI와 관련된 어노테이션)5.Spring IoC&DI(DI와 관련된 어노테이션)
5.Spring IoC&DI(DI와 관련된 어노테이션)
 
PL/SQL - 10g Release1
PL/SQL - 10g Release1PL/SQL - 10g Release1
PL/SQL - 10g Release1
 
Why what how kotlin
Why what how kotlinWhy what how kotlin
Why what how kotlin
 
안드로이드 개발자에 필요한 오픈소스이야기
안드로이드 개발자에 필요한 오픈소스이야기안드로이드 개발자에 필요한 오픈소스이야기
안드로이드 개발자에 필요한 오픈소스이야기
 
[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)
[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)
[Td 2015]너에게만 나는 반응해 반응형 응용프로그램(이규원)
 
델파이와 유니코드
델파이와 유니코드델파이와 유니코드
델파이와 유니코드
 
Kotlin with fp
Kotlin with fpKotlin with fp
Kotlin with fp
 
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
 
Protocol Oriented Programming in Swift
Protocol Oriented Programming in SwiftProtocol Oriented Programming in Swift
Protocol Oriented Programming in Swift
 

Similar to Java8 - Oracle Korea Magazine

Introduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&CIntroduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&Csys4u
 
Implementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4UImplementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4Usys4u
 
Open Source Engineering V2
Open Source Engineering V2Open Source Engineering V2
Open Source Engineering V2YoungSu Son
 
Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드중선 곽
 
Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수Park Jonggun
 
Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드중선 곽
 
자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)Chang-Hwan Han
 
SpringCamp 2013 : About Jdk8
SpringCamp 2013 : About Jdk8SpringCamp 2013 : About Jdk8
SpringCamp 2013 : About Jdk8Sangmin Lee
 
AngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSAngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSKenneth Ceyer
 
LucideWorks Banana 소개
LucideWorks Banana 소개 LucideWorks Banana 소개
LucideWorks Banana 소개 SuHyun Jeon
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 Yong Joon Moon
 
Java jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_streamJava jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_stream성 남궁
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.Ryan Park
 
어플리케이션 성능 최적화 기법
어플리케이션 성능 최적화 기법어플리케이션 성능 최적화 기법
어플리케이션 성능 최적화 기법Daniel Kim
 
프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)Devgear
 
스프링 스터디 1장
스프링 스터디 1장스프링 스터디 1장
스프링 스터디 1장Seongchan Kang
 
Eclipse RAP - Single Source
Eclipse RAP - Single SourceEclipse RAP - Single Source
Eclipse RAP - Single Sourcecho hyun jong
 

Similar to Java8 - Oracle Korea Magazine (20)

Introduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&CIntroduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&C
 
Implementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4UImplementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4U
 
Open Source Engineering V2
Open Source Engineering V2Open Source Engineering V2
Open Source Engineering V2
 
Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드
 
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
 
Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수Start IoT with JavaScript - 6.함수
Start IoT with JavaScript - 6.함수
 
Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드
 
자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)
 
SpringCamp 2013 : About Jdk8
SpringCamp 2013 : About Jdk8SpringCamp 2013 : About Jdk8
SpringCamp 2013 : About Jdk8
 
react-ko.pdf
react-ko.pdfreact-ko.pdf
react-ko.pdf
 
AngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJSAngularJS 2, version 1 and ReactJS
AngularJS 2, version 1 and ReactJS
 
LucideWorks Banana 소개
LucideWorks Banana 소개 LucideWorks Banana 소개
LucideWorks Banana 소개
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
Java jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_streamJava jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_stream
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.
 
어플리케이션 성능 최적화 기법
어플리케이션 성능 최적화 기법어플리케이션 성능 최적화 기법
어플리케이션 성능 최적화 기법
 
프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
스프링 스터디 1장
스프링 스터디 1장스프링 스터디 1장
스프링 스터디 1장
 
Eclipse RAP - Single Source
Eclipse RAP - Single SourceEclipse RAP - Single Source
Eclipse RAP - Single Source
 

More from Jay Lee

Spring on Kubernetes
Spring on KubernetesSpring on Kubernetes
Spring on KubernetesJay Lee
 
Knative And Pivotal Function As a Service
Knative And Pivotal Function As a ServiceKnative And Pivotal Function As a Service
Knative And Pivotal Function As a ServiceJay Lee
 
Knative and Riff
Knative and RiffKnative and Riff
Knative and RiffJay Lee
 
Spring5 New Features
Spring5 New FeaturesSpring5 New Features
Spring5 New FeaturesJay Lee
 
Reactive Microservice And Spring5
Reactive Microservice And Spring5Reactive Microservice And Spring5
Reactive Microservice And Spring5Jay Lee
 
CF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud ServicesCF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud ServicesJay Lee
 
SpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data GemfireSpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data GemfireJay Lee
 
CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF Jay Lee
 
JavaEE6 - 설계 차원의 단순성
JavaEE6 - 설계 차원의 단순성JavaEE6 - 설계 차원의 단순성
JavaEE6 - 설계 차원의 단순성Jay Lee
 
Java EE7
Java EE7Java EE7
Java EE7Jay Lee
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & BeyondJay Lee
 

More from Jay Lee (11)

Spring on Kubernetes
Spring on KubernetesSpring on Kubernetes
Spring on Kubernetes
 
Knative And Pivotal Function As a Service
Knative And Pivotal Function As a ServiceKnative And Pivotal Function As a Service
Knative And Pivotal Function As a Service
 
Knative and Riff
Knative and RiffKnative and Riff
Knative and Riff
 
Spring5 New Features
Spring5 New FeaturesSpring5 New Features
Spring5 New Features
 
Reactive Microservice And Spring5
Reactive Microservice And Spring5Reactive Microservice And Spring5
Reactive Microservice And Spring5
 
CF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud ServicesCF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud Services
 
SpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data GemfireSpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
 
CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF
 
JavaEE6 - 설계 차원의 단순성
JavaEE6 - 설계 차원의 단순성JavaEE6 - 설계 차원의 단순성
JavaEE6 - 설계 차원의 단순성
 
Java EE7
Java EE7Java EE7
Java EE7
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & Beyond
 

Java8 - Oracle Korea Magazine

  • 1. TECHNOLOGY & DEVELOPER 68_ Java8&Beyond
  • 2. Java8 소개 지금으로부터 약 20년 전인 1994년, Sun의 James Gosling 박사는 이후에 프로그래밍 세계를 완벽히 바꿔 놓은 ‘Oak’ 라고 하는 언어를 개발하게 된다. 이것이 바로 현재 전세계 약 900만 이상의 개발자들이 사용하 고 있는 Java의 시초이다. Java는 1996년 1.0 버전이 처음 세상에 나왔고, 2014년 3월 그 여덟 번째 버전인 Java SE8 이 세상에 나올 채비를 갖추었다. Java 가 오늘에 이르기 까지 겪었던 변화들을 살펴보면 먼저 플 랫폼이 모바일, 엔터프라이즈로 세분화 되었고, RMI, Native IO(NIO), XML 파서, Concurrent Utility 등 수 많은 새로운 기능들이 추가 되었으며, Generic 및 Annotation 등의 지원이 추가 되었고, 하드웨어적으로 는 Embedded CPU까지 지원함으로써 엔터프라이즈 시장을 넘어 모바일, Internet of Things 세계에서도 기존 개발자들이 그들의 역량을 그대로 활용할 수 있도록 발전해 왔다. 이러한 진보와 더불어 Java의 오픈 소스 화도 빼놓고 얘기할 수 없을 것 같다. 2006년 JavaOne에서 발표된 오픈 소스화 발표 이후 그 첫 결과 물로 Java SE7 의 Reference Implementation인 OpenJDK가 발표 되었다. 이후 OpenJDK는 오픈 소스 커뮤니티 및 개발자들의 도움으로 빠르게 발전해 왔다. OpenJDK의 대표적인 성공사례로 Taobao(중국의 e-commerce 회사)가 손꼽히고 있는데, 그들의 환경에서 성능 최적화된 Customized JVM을 약 1만개 이 상의 인스턴스에서 운영하고 있다고 한다(JavaOne 2012년 발표 참조). 이렇게 뒤돌아보면 열거할 수 없을 정도로 많은 변화들을 겪어 왔지만 그 중에서도 Java8은 이전에 그 어느 TECHNOLOGY & DEVELOPER Java8&Beyond 저자 - 이창재 컨설턴트, Oracle APAC STAr Team, Senior Architect 2014년 Big Trend 중 하나는 Internet of Things, 일명 IOT라고도 불리며 모든 사물이 인터넷에 연결되어 동작하는 것을 의미한다. 이전에는 Embedded 기기로써 인터넷에 연결되지 않고 개별기기가 동작하는 형태였고, 보통 C나 어셈블리를 통해서 프로그래밍 해왔지만 2014년에는 C나 어셈블리 같은 언어를 따로 배우지 않고도 Java 개발자들이 이러한 Embedded 기기를 위해 프로그래밍하고 인터넷에 연결하여 사물 인터넷을 구성할 수 있게 되었다. 이제 Java는 하나의 플랫폼으로 진화하고 있다. Java라는 언어만 실행하는 것이 아니라 다른 여러 함수형 언어까지 Java Virtual Machine의 그릇에 담고, 서버 뿐만 아니라 Embedded 디바이스 같은 소형 기기에서도 동일한 개발 스킬을 활용할 수 있는 시대가 오고 있다. 2014년 3월에 출시될 Java 8은 이렇듯 언어적인 진화와 더불어 대대적으로 플랫폼적인 진화가 예고되어 있다. 본고에서는 Java 8에 핵심 변화들에 대해서 알아보고자 한다. Technology & Developer Java8&Beyond ORACLE KOREA MAGAZINE Spring 2014 68
  • 3. ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 69 Spring 2014 버전들 보다 더 많은 변화가 예고되어 있다. Interface에 default 메소드, static 메소드 사용이 가능해진 것이 언어 측면에서의 대표적인 변화라고 볼 수 있다. 그리고 특히 이번 버전에서 가장 중요한 기능으로 평가 받고 있는 Lambda는 기존과는 다른 새로운 프로그래밍 방식을 채용하기를 개발자들에게 요구하고 있다. 참고로 Java는 전세계에서 가장 많이 쓰이는 프로그래밍 언어(Github top10 2013년 기준) 중에서 가장 늦게 Lambda expression을 채용한 언어가 되었다. 새 버전에는 이 Lambda를 이용해서 Collection을 좀 더 효율적으로 또한 지금까지 지속적으로 문제가 제기 되어왔던 Time 및 Date 관련 API가 마침내 완전히 새롭게 개선되었다. 성능 및 개발 생산성 측면에서 그동안 어쩔 수 없이 Joda Time이나 Apache commons 라이브러리들을 사용해 왔던 애플리케이션 개발자들에게는 아주 기쁜 소식이 될 것이다. 플랫폼 측면에서는Java7의 invokedynamic의 결실로 JVM 기반에 javascript 엔진 Nashorn 등이 소개 되었다. 그 밖에도 부족한 지면으로 다룰 수는 없지만 NIO2나 Concurrent API 등에 여러 가지 개선이 이루어 졌고 Optional 타입도 소개되었다. 본고는 지면 관계상 가장 주목해야 할 변화들에 초점을 맞추어 설명하였다. <Example Code 1> @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); // 1 boolean equals(Object obj); default Comparator<T> reversed() { //2 return Collections.reverseOrder(this); } ....... 생략 public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) { //3 Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2)); } } Interface 향상 위의 <Example Code 1>은 Java8의 Comparator의 소스를 가져 온 부분이다. 평이한 Interface처럼 보이지만 //2, //3 번을 눈여겨보기 바란다. 먼저 default 메소드에 대해서 알아보자. 이전 버전까지 Interface에 abstract 메소드들은 반드시 클래스에서 해당 메소드들을 구현해 주어야 했다. 어떠한 이유에서든지
  • 4. Interface에 새로운 메소드들이 추가 되는 경우, 소스 코드들을 고쳐줘야 했고(해당 메소드들을 구현), 이로 인해 바이너리 호환성에 이슈가 생길 수밖에 없었다. 이러한 이유로 default 메소드라는 개념이 생기게 되었다. Lambda(이후에 설명할)를 Collection API에 지원하려고 하면서 발생했던 문제를 예를 들어 설명해 보면, Collection Interface에 확장을 위해서 새로운 abstract 메소드가 지정 되는 경우 이를 implement하는 ArrayList, Vector 등 모든 클래스들이 변경되어야 한다. 새롭게 확장할 메소드들을 default 메소드로 지정하는 경우에는 그러한 작업이 필요 없어지는 것이다. 즉 default 메소드는 이를 구현하는 모든 클래스들이 동일한 기능을 사용할 수 있도록 하는 동시에, 인터페이스에 변경이 생기더라도 바이너리 호환성을 유지할 수 있는 방법을 제공해 준다. static 메소드의 허용도 눈 여겨 볼만 하다. 기존에는 abstact 메소드 혹은 필드 변수(암시적으로 static final 로 지정됨)만이 지정 가능했다면 이제는 //3처럼 static 메소드를 직접 Interface 안에서 구현 가능하다. Lambda Expression Lambda는 Java8의 신기능 중에서도 가장 많은 스포트라이트를 받고 있는 기능이다. Lambda의 이해를 위해서 다음의 익명 클래스(anonymous class)의 예를 살펴보자. <Example Code 2> new Thread(new Runnable() { public void run() { System.out.println(“Thread run!!”); } }).run(); Runnable이나 ActionListener 혹은 Comparator처럼 오직 하나의 메소드만을 가진 인터페이스를 SAM(Single Abstract Method Type)이라고 한다. Lambda는 이렇게 오직 하나의 메소드만을 가진 인터페이스를 Functional Interface라고 부른다. <Example Code 1>의 //3에 Comprator가 대표적으로 @ FunctionalInterface annotation을 구현한 인터페이스이다. 코드를 보면 Function Interface의 규칙을 Comparator가 지키고 있는 것 같아 보이지 않는다. 코드는 compareTo()와 equals(),두 메소드가 abstract 메소드로 지정되어 있는데 어떻게 annotation이 허용될까? 그 이유는 바로 equals가 Object의 public 메소드이기 때문이다. Java 언어 스펙에는 모든 Interface는 Object의 public 메소드를 정의하도록 되어 있다. 이러한 이유로 toString이나 equals같은 메소드들은 Functional Interface의 규칙에 위배 되지 않는다. Lambda 표현식의 예를 구체적으로 알아보자. 위의 Runnable 코드를 Lambda로 구현하면 다음과 같이 한 줄로 표현 된다. ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 70 Spring 2014
  • 5. <Example Code 3> Runnable r = () -> { System.out.println(“Thread run!!”); } 기본적으로 Lambda 표현식은: (변수 목록) -> Body 로 표현된다. <Example Code 3>에서 보듯이 run 메소드의 경우 변수를 받지 않으므로 ( )으로 표현 된다. 아래의 예도 같이 살펴보자. (int x, int y) -> x + y (String s) -> { System.out.println(s); } Java8은 Lambda Expression을 지원하는 java.util.function 패키지가 추가 되었다. 지면 관계상 Predicate와 Consumer의 예만 살펴보자. Predicate의 예제 먼저 살펴보면, p.getAge() >=16 처럼 조건 자체를 메소드의 변수로 전달할 수 있다. <Example Code 4> Predicate<Person> allDrivers = p -> p.getAge() >= 16; public void phoneContacts(List<Person> pl, Predicate<Person> pred){ for(Person p:pl){ if (pred.test(p)){ roboCall(p); } } } Function의 코드 예제도 살펴보자. 아래의 <Example Code 5>은 westernStype이라고 하는 Function 자체를 전달해서 Person 오브젝트를 Western 스타일의 이름으로 출력해 주는 예제이다. java.util.function.Predicate 변수로 전달된 오브젝트의 속성 java.util.function.Consumer 변수로 전달된 오브젝트에 수행할 액션. 리턴 값 없음 java.util.function.Function<T,U> T를 U로 변경 java.util.function.Supplier<T> <T>를 만드는 인스턴스(대표적으로 Factory 클래스) java.util.function.UnaryOperator 단항(Unary) 연산 java.util.function.BinaryOperator<T,T> 복수항(Binary) 연산 ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 71 Spring 2014
  • 6. <Example Code 5> public String printCustom(Function <Person, String> f){ return f.apply(this); } Function<Person, String> westernStyle = p -> { return "nName: " + p.getGivenName() + " " + p.getSurName() + "n" +"Age: " + p.getAge() + " " + "Gender: " + p.getGender() + "n" +"EMail: " + p.getEmail() + "n" + "Phone: " + p.getPhone() + "n" + "Address: " + p.getAddress(); }; System.out.println("n===Western List==="); for (Person person:list1){ System.out.println(person.printCustom(westernStyle)); } <Example Code 5>에서처럼 Lambda는 기능 혹은 코드 자체를 다른 메소드로 전달할 수 있는 기능을 제공함으로써 이전 보다 더 간결하고 유연한 프로그래밍이 가능해졌다. Stream API 이전 버전에서 Collection은 항상 Iterator를 통해 for 혹은 while 구문을 사용하여 접근했었다. Java8 에서는 java.util.stream 패키지와 Lambda를 활용하여 이전 보다 훨씬 세련되고 향상된 방법으로 Collection을 처리할 수 있게 되었다. stream은 순차(sequential), 그리고 병렬(parallel) 두 종류로 존재한다. 순차 스트림의 경우는 싱글 쓰레드로 순차대로 처리될 것이고 병렬 스트림은 stream이 Fork/Join 프레임워크로 구현된 메소드에 의해서 병렬로 처리된다. 코드 예를 살펴보자. <Example Code 6> int totalCountOfOrder = orderList.stream() .filter(b -> b.getProduct() == "iPhone") .map(b -> b.getAmount()) .sum(); <Example Code 6>을 보자. filter의 경우 Predicate 형을 받아서 처리하여 Stream(T) 형으로 돌려주게 되고, 이를 map이 Function을 매개변수로 받아서 처리한 후에 타겟 타입이 int이므로 IntStream으로 돌려주면 sum이 이를 합해서 최종 결과를 도출해 낸다. 위에 예제에서 map 이나 filter 같은 연산자들은 임시 연산자(Intermediate Operator)라고 불리며 작업 결과를 뒤로 전달해 주는 역할을 한다. 앞에 sum이나 forEach, count 등은 종료 연산자(Terminal Operator)라 불리며 말 그대로 최종적으로 Stream을 처리하는 역할을 한다. parallelStream의 예도 살펴보자. 다음의 코드는 모든 파일럿들의 나이(getAge)의 평균 ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 72 Spring 2014
  • 7. (average)을 병렬로 구하는 예이다. <Example Code 7> OptionalDouble averageAge = pl .parallelStream() .filter(search.getCriteria("allPilots")) .mapToDouble(p -> p.getAge()) .average(); Stream의 사용에 있어서 장단점을 살펴 보면 먼저 장점으로 Laziness를 들 수 있다. 즉 Collection에 iteration 처리를 자바에게 맡겨둠으로써 JVM 이 코드에 대한 처리를 최적화할 수 있는 기회를 제공한다. 단점 및 주의해야 할 사항으로 stream 은 재사용이 불가능 하다는 것이다. 한번 사용된 stream은 재사용이 불가능하며, 필요에 따라서 새롭게 만들어져야 한다. Time And Date API 프로그래밍을 하면서 가장 흔하게 접하게 되는 요구사항 중에서 날짜 및 시간의 처리가 빠질 수가 없을 것이다. Java에는 1.0부터 java.util.Calendar, java.util.Date 등의 API를 제공해 왔다. 그렇다면 어떠한 문제가 있었길래 그동안 개발자 커뮤니티에서 지속적으로 개선에 대해 요구해 왔고 어떠한 식으로 개선이 되었는지를 살펴보자. 가장 잘 알려진 문제점부터 나열해 보면: 1. 년은 1900년부터 시작한다. 1900년도 이전에 대한 처리는 workaround가 필요. 2. 월이 1부터가 아닌 0부터 시작한다. 그러므로 12월은 실제로 숫자 11이다. 3. Mutable하므로 thread safe하지 않다. 4. Performance 문제 이러한 문제들 외에도 직관적이지 않고 각각의 처리를 위해서 추가적인 클래스들이 필요(예를 들어 SimpleDateFormat 같은)한 것 등이 문제점으로 지적되어 왔다. Java8에 새롭게 추가된 Time And Date API는 Joda Time을 만든 Stephane Coleburne가 리딩하고 있는 JSR-310을 기반으로 하고 있다. 새롭게 만들어진 Time And Date API는 java.util.Date, java.util.Calendar, java.util.TimeZone, java.util. DateFormat이 4개를 전부 대체하고 있다. 새롭게 추가된 java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time. ZonedDateTime 등이 이를 대체하게 된다. LocalDate의 경우 년-월-일, LocalTime은 시-분-초-나노초, LocalDateTime은 년-월-일-시-분-초를 내부적으로 저장한다. 각각의 API 에 대한 사용 예는 <Example Code 7>을 살펴보자. ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 73 Spring 2014
  • 8. <Example Code 7> LocalDate currentDate = LocalDate.now(); boolean isLeapYear = currentDate.isLeapYear(); LocalDate date = LocalDate.of(2014, Month.FEBRUARY, 12); LocalTime currentTime = LocalTime.now(); LocalDateTime currentDateTime = LocalDateTime.now(); currentDateTime = LocalDateTime.of(2014, 2, 21, 13, 40); date = currentDateTime.plusMonths(1).minusDays(3); 시간 및 날짜의 조정은 plus/minus/with 등 알기 쉬운 명칭의 API 로 변경 되었다. TimeZone 지원은 ZonedDateTime을 통해 이루어지며 내부적으로는 LocalDateTime, ZoneId, ZoneOffset이 3가지가 저장된다. ZoneId의 경우 “Europe/London”, “Asia/Seoul” 등으로 표현 되며 ZoneOffset은 -18:00부터 +18:00의 범위로 표현된다. 한국의 경우는 +09:00으로 표현된다. 이외에도 java.time에는 Instant, Amount, Duration, Period 등의 클래스들이 추가 되었다. Type Annotation Java8에 추가된 Type Annotation은 새롭게 type 시스템에 추가된 기능으로, 어떠한 type, 예를 들어 새로운 operator나 implements구문, throws구문 등에 추가할 수 있는 annotation이다. <Example Code 8> @NotNull String str1 = ... @Email String str2 = ... @NotNull @NotBlank String str3 = ... Map.@NonNull Entry = ... myString = (@NonNull String) myObject; void monitorTemperature() throws @Critical TemperatureException { ... } void authenticate() throws @Fatal @Logged AccessDeniedException { ... } <Example Code 8>에서 보듯이 @NotNull @Email 등의 type annotation을 통해서 해당 변수에 대한 type을 지정해 줄 수 있다. 또한 throws 같은 구문에도 annotation을 지정하는 것이 가능하다. 이렇게 언어적으로 상당히 유용한 기능이 추가 되었지만, 한 가지 유의할 점은 현재 자바 컴파일러가 지정된 type에 대한 사용을 강제하지 않는 다는 것이다. 즉 annotation 사용이 가능하고 컴파일이 가능하지만, 실 ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 74 Spring 2014
  • 9. 제로 지정된 type을 준수하는지에 대한 체크는 IDE 나 별도의 Framework(Checker Framework)을 이용해야 한다는 것이다. Repeating Annotation 기존에는 동일한 Annotation의 중복 선언은 허용되지 않았다. Java8부터는 동일한 Annotation의 중복 선언이 허용 된다. java.lang.annotation.Repeatable이 새로 소개되었다. 다음의 <Example Code 9>는 주기적으로 어떤 작업을 수행하는 Scheduler에 복수개의 Schedule을 annotation을 이용해서 지정한 예이다. <Example Code 9> @Schedule(dayOfMonth="last") @Schedule(dayOfWeek="Fri", hour="23") public void doPeriodicCleanup() { ... } JDK Convergence 현재 Oracle은 Hotspot과 JRockit JVM 두 가지를 고객에게 제공하고 있다. JRockit JVM 은 BEA에서 Oracle로 넘어온 JVM이고 특히 JRockit Realtime(JRRT)는 Latency가 중요한 고객들에게 Deterministic GC를 제공함으로써 안정적으로 시스템을 운영할 수 있는 장점을 제공해 왔다. Oracle은 JRockit이 가진 강점을 Hotspot에 접목 시켜서 하나의 JVM으로 만들기로 결정을 내렸고, 이러한 Convergence의 결과물이 Java7 Update 40에서 처음으로 소개 되었다. 바로 Java Mission Control과 Flight Recorder가 그것인데, JMC는 <그림1>과 같이 현재 JVM에서 벌어지는 상황을 GUI로 한눈에 확인할 수 있는 툴이고, Flight Recorder는 실제 JVM이 실행될 때의 모든 Metric을 저장해서 마치 비행기의 블랙박스처럼 나중에 돌려 보고 문제를 파악할 수 있는 기능을 제공한다. JDK Convergence는 Java8에서도 계속되는데 대표적으로 Permanent 영역이 사라졌다. Perm 영역에 저장되었던 정보들 중에서 String Constant Pool은 Heap 영역으로 이동 되었고, 기타 클래스 메타데이타 정보 같은 것들은 Metaspace라고 하는 Native Memory 영역으로 이동 되었다. 이 영역은 MaxMetaspaceSize 옵션을 통해서 사이즈를 지정해 줄 수 있으며, 이 영역도 Garbage <그림 1> Java Mission Control 화면 ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 75 Spring 2014
  • 10. Collection 이라는 개념이 존재한다. 이후 JDK8 Update로써 JRockit Realtime의 Deterministic GC 기능과 비슷한 Deterministic G1 기능이 제공될 예정이다. Compact Profile Oracle은 JavaOne에서 Java ME와 SE의 convergence에 대해서 소개한 바 있다. Convergence 작업에 일환으로 Java8부터는 Java ME/CDC가 Java SE Embedded에 의해 대체된다. 이 Java SE Embedded에 근간이 되는 것이 바로 Compact Profile이다. Raspberry Pi나 PandaBoard 등이 대표적인 타겟 플랫폼이 될 것이다. 정식 버전 출시 전이라 얼마나 ‘Compact’ 한지 정확한 자료를 제공하긴 어렵지만 Early Access 버전을 테스트한 자료에 따르면 ARMv5/Linux 기준으로 Compact 1은 대략 14MB, Compact 2는 대략 18MB, Compact 3는 21MB 정도의 footprint를 나타내고 있다. Project Nashorn Javascript를 JVM 에서 동작시킨다는 아이디어는 꽤 오래 전으로 거슬러 올라간다. Wikipedia에 따르면 1997년 Netscape가 100% Java 기반에 브라우저를 만들려고 계획하면서부터 시작되었다고 한다. 그 당시에 프로젝트 이름은 ‘Rhino’라고 하며(이 이름도 O’Reilly의 Javascript책 표지에서부터 비롯되었다고 한다), ‘Nashorn’은 바로 Rhino의 독일어라고 한다. Rhino는 ECMAScript 5.1 표준을 완벽히 구현하고 있으며 Java SE 8 및 ME 8에 모두 소개될 예정이다. Nashorn에 대해서 이야기하기 위해서 먼저 JDK 7에 새롭게 소개된 invokedynamic을 살펴 보자. 앞에서 소개한 Lambda는 내부적으로 이 invokedynamic을 활용한다. invokedynamic은 JVM 의 플랫폼화를 이야기하기 위한 필수적인 개념이다. 자바는 언어적으로 static type 언어라고 불리며 이것은 컴파일 타임에서 이미 멤버 변수들이나 함수의 변수들의 타입이 반드시 명시적으로 지정되어야 함을 의미한다. 그에 반해 Ruby 나 javscript 들은 이른바 ‘duck-typing’ 이라고 하는 타입 시스템을 채용함으로써 컴파일타임에서의 ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 76 Spring 2014 <그림 2> shell scripting <그림 3> Shelling Script 실행
  • 11. type을 강제 하지 않는다. invokedynamic은 이러한 duck-typing을 JVM 레벨에서 기본적으로 지원하면서 Java 외에 다른 언어들이 JVM이라는 플랫폼 위에서 최적화된 방식으로 실행될 수 있는 토대를 제공해 준다. Java8에는 jjs라고 하는 커맨드라인 툴을 이용해서 Nashorn 엔진을 호출할 수 있다. <그림 2, 3>의 예에서 보듯이 자바스크립트 안에서 직접 Java Class 들을 생성하고 호출할 수 있다. 또한 JavaFX 애플리케이션을 실행할 수도 있다. 맺음말 Java8에 새롭게 소개된 기능들에 대해서 간략히 살펴보았다. 소개한 대로 많은 변화들이 이루어 졌으며 또한 그 동안 개발자들에게 pain point였던 부분들이 상당 부분 개선되었음을 알 수 있다. 본래부터 Java는 2년 주기의 메이저 업데이트를 통해서 빠르게 새로운 기술들이 채용되고 소개되어 왔다. 물론 2006년 Java6 에서 2011년 Java7으로 이 사이클이 깨어지긴 했지만, 내부적인 이유(Sun Microsystems의 합병)와 외부적인 이유(OpenJDK)의 복합적인 작용이 컸었던 만큼 앞으로는 다시 2년 주기로 새로운 버전이 나올 예정이다. 보안 이슈로 1년 미루어진 Java8 버전부터 다시 본래의 주기로 돌아오게 되면 앞으로는 이러한 변화들을 체감 속도보다 더 빠르게 그리고 지속적으로 체감할 것으로 예상 된다. 이 글을 읽고 난 후에 독자들이 가질 가장 큰 의문은 “새로운 기능이 좋아 보이긴 하는데 Java8을 당장 채용해도 될까?”일 것이다. 여기에 대한 대답으로 필자는 손자병법을 인용하면서 글을 마무리 하고자 한다. 손자병법에는 應形無窮(응형무궁)이란 말이 있다. “끊임없는 변화에 준비하고 대응하라”라는 뜻이다. Java7, 8에서의 변화는 Java가 앞으로 새로운 10년을 나아가는 데에 있어서 디딤돌이 될 것임을 개인적으로 예상하는 바이고, 이 끊임없는 변화에 준비하고 대응하기 위해서, 그러므로 가장 먼저 해야 할 일이 바로 Java8을 채용하는 일일 것이다. Java8 버전은 이 글을 작성하고 있는 2014년 2월 현재 https://jdk8.java.net/ download.html에서 다운로드 받을 수 있다. ORACLE KOREA MAGAZINE Technology & Developer Java8&Beyond 77 Spring 2014
  • 12. Copyright © 2009, Oracle. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. oracle.com/goto/industries또는 080.2194.114로 문의하세요. #1 Development PlatformComputers, Printers, Routers, BlackBerry Smartphones, Cell Phones, Kindle E-Readers, Parking Meters, Vehicle Diagnostic Systems, On-Board Computer Systems, Smart Grid Meters, Lottery Systems, Airplane Systems, ATMs, Government IDs, Public Transportation Passes, Credit Cards, VoIP Phones, Livescribe Smartpens, MRIs, CT Scanners, Robots, Home Security Systems, TVs, Cable Boxes, PlayStation Consoles, Blu-ray Disc Players… 30억개의디바이스에서자바를 운영합니다PRODUCTION