메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

Java 9에 대해 모든 자바 개발자들이 알아야 할 것 : 새로운 HTTP 클라이언트 지원과 JSON API 통합에 대해

한빛미디어

|

2014-12-08

|

by HANBIT

21,716

제공 : 한빛 네트워크
저자 : Ben Evans
역자 : 한승균
원문 : What every Java developer needs to know about Java 9

Java 9 Java 8이 발표된 지 몇 달 지나지도 않았는데, 오라클은 벌써 Java 9에서 지원할 기능 중 일부를 발표했다. 자바 수석 아키텍트인 Mark Reinhold는 jdk9-dev 메일링 구독자들에게 기능들을 공개했다.

이 기능들은 Java Enhancement Proposals(JEP)라 불리는, 새로운 프로세스를 통해 구현되고 있다. 적당하고 성공적인 JEP는 표준 정규화 프로세스를 따르게 될 것이라고 기대하고는 있지만, 이 프로세스는 정식 자바 표준화 프로세스를 신경 쓰지 않고도 새로운 언어와 VM 기능을 구현해볼 수 있도록 허용하고 있다. 그리고 당연하게도, Java 9에는 새로운 기능들이 많이 소개될 것이지만, 이 포스트에서는 두 가지 중요한 부분에 집중하려고 한다 - 그리고 그것들이 Java 7과 8에 추가된 기능들과는 어떤 관계를 가지게 되는지 알아볼 것이다.

새로운 HTTP 클라이언트

자바가 HTTP를 지원하는 핵심 부분은 Java 1.1(1997년에)에서 처음 소개된 후로 거의 그대로다. 이런 상황은 많은 이유로 현재에는 맞지 않은데, 가장 중요한 점은 HTTP가 사실상 다른 프로토콜들보다 훨씬 더 우세하게 사용되고 있다는 것이다. 이것은 자바가 채용했던 원래의 접근 방식(여러 프로토콜을 지원하기 위해 URLConnection을 사용했던 방식)을 구식이며, 불필요하게 복잡하게 만들었다. 처음의 API도 문제인데, HTTP 1.0만을 구현했기 때문에 네트워크 오버헤드 관점에서 아주 비싼 비용을 들이게 된다.

물론, HTTP 지원이 처음 추가되었을 때 이후로, 17년 동안 개선된 부분도 있다. 가장 중요한 부분은 Java 7과 try-with-resources 구문과 함께 다가왔다. 이것들은 아래와 같은 코드가 가능케 했다:
URL url = new URL("http://www.oreilly.com/");
try (InputStream in = url.openStream()) {
  Files.copy(in, Paths.get("output.txt"));
} catch(IOException ex) {
  ex.printStackTrace();
}
이 코드 조각은 현재 HTTP 클라이언트를 구현하는 가장 간단한 방법이다. 불행하게도, 긍정적인 부분만 있는 것은 아니다. 만약 HTTP 연결에 대해 다른 것들을 더 조절하고 싶다면(예를 들어, HTTP 데이터와 헤더를 모두 살펴보는 등), 아래와 같이 구현할 수 있다:
try {
  URLConnection conn = url.openConnection();
 
  String type = conn.getContentType();
  String encoding = conn.getContentEncoding();
  Date lastModified = new Date(conn.getLastModified());
  int len = conn.getContentLength();
  InputStream in = conn.getInputStream();
} catch (IOException e) {
  // Handle exception
}
자바 8 람다 : 자바 개발자를 위한 함수형 프로그래밍 이 경우, URLConnection 클래스가 AutoCloseable 인터페이스를 구현하지 않아서 URLConnection 타입의 변수들은 try-with-resources 구분을 사용할 수 없다. 때문에 HTTP 처리가 개선되어도 우리가 좋아할 정도로 상황이 개선되지는 않았다. 그 사이의 많은 시간 동안, 자바 개발자들은 Apache 같은 곳에서 제공하는 다른 HTTP 라이브러리들을 사용하기 시작했다. 이러한 라이브러리들은 어떤 부분에서는 더 훌륭했으나, 그것들도 완벽하지는 않았다. 그리고 - 이 포스트를 쓰는 현재까지는 - 아무 것도 Java 8 기능의 (람다와 같은) 장점을 활용하지 못하고 있다.

이것들을 염두 해 둘 때, JDK 핵심 라이브러리의 새로운 HTTP API는 명확해 보였다. 일부 예비 작업은 JDK 8에서 진행되었으나, 발표 날짜 전에 모두 완성하기에는 시간이 충분치 않았다. 이번에 HTTP 지원이 개선됐다면 좋았을 테지만, Java 9까지 연기되었다는 점은 새 버전의 HTTP 프로토콜(HTTP/2)의 장점을 취할 수 있게 될 것이라는 점을 의미한다. 이 새로운 HTTP(이전에는 HTTP/2.0 이라고 불렸던)는 2014년 11월까지 완성될 것으로 예상되고 있으며, Java 9 발표일까지는 시간이 많이 있다. 새로운 Java 9 HTTP API 문법이 어떤 모습이 될지는 알 수 없으나, 이 새로운 프로토콜을 지원하는 것은 이 프로젝트의 중요한 목표다.

JEP 페이지OpenJDK 네트워킹 지원 메일링에서 더 많은 정보와 API 개발 및 지원 코드를 살펴볼 수 있다.

새로운 JSON API

자바는 XML과 웹 서비스를 훌륭하게 지원하지만, XML이 과거에는 데이터 포맷 중의 하나로 사용되었던 것에 비하면 최근 몇 년동안 그 빛을 잃고 있다. 대신, 세상은 REST 스타일의 간단한 웹 서비스를 통해 전달되는 JSON으로 이동해갔다. EE 7 표준에서는, 이 기술을 어느 정도 지원한다. 예를 들어, 다음의 인증 데이터로 세션을 초기화하는 간단한 웹 서비스를 생각해보자:
@Path("session")
@Produces("application/json")
public class SessionService {
 
    private static final Logger logger = LoggerFactory.getLogger(SessionService.class);
 
    @POST
    @Consumes("application/json")
    public Response createSession(AuthData auth) {
        long start = System.currentTimeMillis();
        logger.info("Incoming: " + auth);
 
        final Session session = validate(auth);
 
        if (session == null) {
            return Response.notAcceptable(null).build();
        }
 
        long end = System.currentTimeMillis();
        logger.info("Request took: " + (end - start) + " ms");
 
        return Response.ok(session).build();
    }
 
    public Session validate(AuthData auth) {
        if (auth == null) {
            return null;
        }
        // Other validation
 
        return new Session(auth);
    }
}
어노테이션들은 명확해 보인다 - 이것은 애플리케이션 (혹은 WAR 파일의) 루트의 하위 디렉토리인 session에 존재하는 웹 서비스이다. 이것은 JSON 데이터를 생성(송신)하기도 하고, 사용(수진)하기도 하며, HTTP POST 방식으로 데이터를 받는다고 가정한다. 여기에는 자바 객체를 JSON으로 매핑하기 위한 비밀의 마법 같은 것이 있으나, 이 매퍼들은 상대적으로 사용하고 설정하는 것이 직관적이다.

이건 Java EE 개발자들에게 좋은 점이겠지만, SE만 사용해야 하는 프로젝트인 경우는 어떤가? 다행히, Java 8에는 아주 도움이 되는 기능이 있다. Nashorn이라고 알려진 새로운 자바스크립트 구현이다. 이것은 더 최신의, 완전하게 업데이트 된 자바스크립트 버전을 구현한 것으로, 더 오래된 버전인 Rhino 구현(Nashorn은 "Rhino"의 독일어이다.)을 대체한다. Nashorn은 자바스크립트 표준과 완전히 호환되며, JVM의 이점을 적극적으로 활용한다. 게다가, Nashorn 기능은 Java와 쌍방향으로 굉장히 긴밀하게 통합되어 있다. 자바 프로그램에서 Nashorn을 이용해 자바스크립트 코드를 실행하는 간단한 예제를 살펴보자:
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
 
try {
  e.eval("print("Hello World!");");
} catch (ScriptException se) {
  // ... Handle exception
}
이 예제는 Java 6에서 소개된 스크립트 엔진 메커니즘을 사용한다. 하지만 자바스크립트의 REPL(Read-Eval-Print-Loop)을 콘솔에서 실행할 수 있기 때문에, Nashorn을 바로 실험해볼 수 있다. 만약 Java 8이 설치되어 있고, path 설정에 JAVA_HOME의 bin 디렉토리가 포함되어 있다면, jjs라고 치면 REPL이 나타날 것이다:
jjs> print("Hello World!");
Hello World!
이것은 잘 동작하지만, 너무 간단한 예제다. 좀 더 복잡한 예제를 통해 자바와의 통합이 어떻게 동작하는지 알아보자. 실제로는, 자바스크립트 함수는 람다 표현식과 같이 다루어진다. 그래서 이렇게 코드를 작성할 수 있다:
jjs> var clz = Java.type("java.util.concurrent.Callable");
jjs> var obj = new clz(function () { print("Foo"); } );
jjs> obj.call();
Foo
그렇다 - 우리는 자바스크립트 함수를 람다 표현식처럼 다룰 수 있는데, 이 람다 표현식은 Callable로 자동으로 변환이 가능하다. 그래서 우리는 결과 객체에 있는 call 메소드를 사용할 수 있다.

자바스크립트 코드를 자바와 함께 사용하는 것에 비용이 들기는 하지만, Nashorn은 parse()와 stringify()를 통해 JSON을 아래 예제에서 보듯이 완벽하게 지원한다:
jjs> var me = JSON.parse("{"name":"Ben Evans",
"details":{"dob":"1976-05-21", "gender":"Male"}}");
jjs> print(me.name);
Ben Evans
jjs> print(JSON.stringify(me));
{"name":"Ben Evans","details":{"dob":"1976-05-21","gender":"Male"}}
게다가 Nashorn이 Java 8에서 구현되는 동안, 2013년 5월에 배포되어 EE 7에 포함된 (하지만 SE 8의 표준은 되지 못한) JSR 353이 만들어지고 있었다. Java 9은 JSON을 다루는 새롭고 매우 효율적인 API를 제공함으로써 이것을 개선시키고 싶어한다. 오라클은 새로운 JSON API가 JSR 353에서 최우선적으로 구현될지 여부는 발표하지 않았지만, 그 사이에, 여기에 새로운 API를 위한 JEP 페이지가 여기 생겼다: http://openjdk.java.net/jeps/198; 관련된 토론은 OpenJDK core libraries 메일링에서 찾아볼 수 있다.

마침내, 이 API들이 자바 사용자 그룹 안에서 널리 사용될 것이 분명해지면서, 이 발전적인 프로젝트를 추적하는 Adopt 그룹의 생성이 거의 확실해졌다. 만약 당신이 참여하는데 관심이 있다면, 개발자들이 참여하고 개발을 시작하며, API를 테스트 할 수 있도록, 그룹이 언제 준비될지 알려줄 공지를 기다려보라.
TAG :
댓글 입력
자료실