생소해 Kotlin

생소해 Kotlin #1

Kotlin은 JVM 언어이고 Java와 호환성을 가지고 있기 때문에 Java와 비슷한 맥락을 가지고 있을 것이란 어설픈 추축들을 해왔다. 하지만 보면 볼 수록 익숙하지 않은 부분들이 눈에 들어와 그것들을 정리해보자.

생소한 Type

Kotlin 코드를 보면서 생소한 Type들에 대해 모아봤습니다.

Unit

  • Javadoc 설명 : The type with only one value: the Unit object. This type corresponds to the void type in Java.
    • Java의 void와 같은 것이라고 함. 값 하나에대한 타입이 void? 역시 이런 것은 예제가 필요함.
  • Unit-retruning functions
  fun printStr(value: String): Unit {
    println(value)
  }

  // ^^^ vvv 위아래 동일한 것임.

  fun printStr(value: String) {
    println(value)
  }
  • 아마도 함수 레퍼런스를 선언할때 void 함수의 표현을 위해 Unit type이 사용되어 Java의 void와 동일하다고 하는 것 같다.
var voidFunc: () -> Void = {} //요런게 없기 때문에
var voidFunc: () -> Unit = {} //요렇게 하는 것.

Any

  • Javadoc 설명 : The root of the Kotlin class hierarchy. Every Kotlin class has Any as a superclass.

  • Java의 ‘Object’와 매칭되는 super class. Object와 다른 것은 Any가 apply let run to 등을 extension으로 가지고 있다는 점.

Nothing

  • Javadoc 설명 : Nothing has no instances. You can use Nothing to represent “a value that never exists”: for example, if a function has the return type of Nothing, it means that it never returns (always throws an exception).

  • 함수가 명시적으로 return이 존재하지 않는다고 표기하기위한 class. 한마디로 종료되지 않는 blocking 함수 같은 것. 이것을 종료하려면 exception 만이 가능

  //일반적인 return 값이 없는 void 함수
  fun noReturn() {
    println("This method returns nothing.")
  }

  //return이 존재하지 않는다고 선언한 함수....
  fun noReturn() : Nothing {
    println("This method never returns.")
  }
  • 위의 Nothing 반환 함수는 Nothing type의 값을 return 하라고 error가 발생한다. 하지만 목적은 return을 안하는 것이기 때문에 선언 시에 생각했던 로직이 변경되었거나 처음 디자인과는 다르게 잘못 만들어진 부분이 있는 것이니 return Nothing 선언을 변경하거나 코드 수정을 해야한다. 얼마나 유용할지는 아직 코알못이라 잘 모르겠네.

Pair / Triple

  • Javadoc 설명 : There is no meaning attached to values in this class, it can be used for any purpose.
    • 말 그대로 다양한 목적으로 쓸수 있게 단순히 object에 값을 더하는 것 뿐. Pair와 Triple의 차이는 단지 그 값의 개수가 2개냐 3개냐 차이
  • 사실 이 기능은 함수 디자인이나 실제 구현시 정말 많은 편의성을 부여한다. 함수 구현시에 한 개 이상의 값을 반환하는 경우에 방법이 없어 Bean을 따로 생성했던 경험이 있는 사람이라면, 그 확장성이 더 없는 Bean class를 선언하고 getter/setter를 만들고 헀던 귀차니즘을 단박에 줄일 수 있다. Generic으로 각 값의 Type도 지정이 가능하니 거의 완벽! 이것만 봐도 Kotlin은 Java에 개발 편의성을 많이 고민했단 생각이 든다. 정말 개발자 친화적이야. 개인적으로 이 Type은 완소!
  • Lombok은 어차피 kotlin의 data class와 마찬가지이니 단순 getter/setter줄이는 것 이외에도 장점이 많다.
  //Java
  public Profile getProfile() {
    Profile a = new Profile();
    a.setName("nurinamu");
    a.setAge(10);
    return a;
  }

  public static void main(String args[]) {
    Profile me = getProfile();
    System.out.println(me.getName());
    System.out.println(me.getAge());
  }

  class Profile{
    private String name;
    private Integer age;

    public void setName(String name) {
      this.name = name;
    }

    public String getName() {
      return this.name;
    }

    public void setAge(String age) {
      this.age = age;
    }

    public Integer getAge() {
      return this.age;
    }
  }

  //kotlin - wow!
  fun getProfile(): Pair<String,Int> = Pair("nurinamu", 10)

  fun main(args: Array<String>) {
    var (name,age) = getProfile()
    println(name)
    println(age)
  }

이 글에서는 생소한 Type들만 쓰는 것으로. 사실 Keyword, Syntax도 한번에 쓰려고 했는데 static blog에서 글이 길어지면 호흡도 길어지고 publishing 타이밍도 놓쳐서 늘어지느라 나눠 쓰기로!

---------------------------------------- "생소해 Kotlin" 끝 ----------------------------------------
Kotlin 첫 Commit Push

오늘 회사 코드에 Kotlin 첫 commit을 push 했다.

Kotlin 파일 하나 작성한 것 뿐인데. 왜이리 호들갑인가 할 수 있겠지만, 근래에 다시 떨어지고 있는 코딩에 대한 재미를 다시 찾을 수 있을 것 같은 언어이고 이 기회에 회사 업무에 써볼 수 있게되는 초석이되었기에 기념을 하려고 글 한 조각 남긴다.

Kotlin과 나

  • Kotlin에 대한 설명은 굳이 안해도 너무 유명.
  • Google Appengine를 써오면서 Java7에 생각이 고착화되고 많이들 회자되는 RX나 FP등의 Modern Language Code들의 트랜드를 많이 놓치고 있었다. Kotlin을 공부 함으로써 뒤쳐진 부분을 좀 채워나갈 생각.
  • 사실 Kotlin 보다 먼저 진행하려했던 Python은 이상하게 계속 진도를 뽑지를 못하고 있다. 원인은 동기부여 부족? ML을 공부하고 TensorFlow를 쓰면서 Python을 습득하려 했는데 오히려 ML 공부에 빠져들면서 정작 TF는 근처에도 못가고 있다. 결국 Python 시작도 못하는 아이러니.
  • Kotlin push 기념을 핑계 삼아 다시 블로그에 글을 올리고, kotlin 공부하면서 느껴지는 java와의 비교 점들을 남겨보고 싶다. 어느 언어가 뛰어나다의 이야기보다는 써보니 이런 점이 편하고 불편하다의 개인 감상을 남길 계획.
---------------------------------------- "Kotlin 첫 Commit Push" 끝 ----------------------------------------
2016.08.08 오늘의 구글링

오늘의 구글링

class안 private 변수 선언만 있고 setter가 없는데 잘되는 코드가 있다. 뭐지?

  • query : project lombok
    • Project Lombok
    • Java코드의 반복작업이되는 Getter/Setter 뿐아니라 toString/hashcode 등 자주 overwrite되는 함수들을 다이어트 시켜주는 Annotation base processor다.
    • 이제야 이런 것을 알다니; 다른 사람 코드 보다가 너무 늦게 입문.
    • 역시 무식하면 손발이 고생이다를 꺠우침.
  • 결과 : lombok을 써보고 혹시모를 단점들도 좀 찾아보자
---------------------------------------- "2016.08.08 오늘의 구글링" 끝 ----------------------------------------
2016.07.09 오늘의 구글링

오늘의 구글링

nginx 넣은 도커가 실행하자마자 죽어버리는데 왜이러지?

  • query : docker container is exited after run
  • 결과 : nginx가 foreground에서 실행되도록 바꾸자.
---------------------------------------- "2016.07.09 오늘의 구글링" 끝 ----------------------------------------
Google Container Engine으로 서버 환경 구축해보기 1편

Google Container Engine으로 서버 환경 구축해보기 1편

GDG 모임에서 이런저런 이야기나오다가 토이프로젝트를 해보자는 말에 그동안 미뤄왔던 Docker와 Java8 관련 코딩을 한번 해보자는 생각에 시작해봅니다.

일단 Hello World까지 만들 서버 환경은 - Google Container Engine + Docker - JDK8 - nginx + tomcat - Spring

Google Container Engine + Docker

그럼 일단 Docker Image 부터 만들어보자.

nginx + tomcat 연동하기

mac에서 Docker가 지원된다고 하니 굳이 cloud 환경에서 만들어서 올리지말고 내 로컬에서 해보기로 합니다. 일단 Docker를 처음 써보는 것이니 튜토리얼 투어를 떠나 봅니다. - Getting Started with Docker for Mac - 내가 필요한 Docker Image 만들기 : 튜토리얼 보고 학습한 다음에 기본기입니다.

제가 위의 예제로 만들어둔 nurinamu/ubuntu:basic 이미지를 여기에서 이용합니다.

80포트를 열어서 이미지를 docker로 올려봅니다. $ docker run -t -i -p 80:80 nurinamu/ubuntu:basic /bin/bash

컨테이너 안으로 들어가서 이제 nginx를 실행합니다.

container# service nginx start

브라우저로 http://localhost에 접근해서 Welcome to nginx!를 확인합니다. 이제 그럼 tomcatnginx에 연결해봅시다.

연결하기 이전에 우선 nginxtomcat의 처리 부분을 결정합니다. 저는 모든 request가 기본적으로는 tomcat에 연결되도록하고 아래의 request들을 예외 부분으로 처리해서 nginx로 보내려고 합니다.

  • 확장자가 js, css, html 인 것들
  • 지정 폴더 하위의 모든 것들 /imgs, /assets

보면 알겠지만 WAS complie이 필요없는 것들만 처리하도록 합니다. 그래서 만들어진 설정은 아래와 같습니다.

nginx.conf 파일

location / {
  proxy_pass http://localhost:8080; #8080으로 프록시 연결
}

location /assets {
  root /assets
}

location /imgs {
  root /assets/imgs
}

설정을 바꿨으니 nginx 재시작

# service nginx restart

이제 톰캣을 실행합니다.

# cd CATALINA_HOME/bin
# ./startup.sh

그럼 이제 다시 http://localhost 에 접근하면 tomcat home이 표시됩니다.

이제 만들어진 이미지를 자기가 원하는 이름으로 이미지 저장합니다.

자동 실행되도록 설정하기

이제 컨테이너가 Docker에 올라가는 시점에 웹서버가 바로 실행될 수 있도록 설정을 합니다. 우선 nginxnginx.conf에 아래 내용을 첫라인에 추가합니다.

daemon off;

위 한줄을 추가하면 nginx가 daemon이되어 background로 빠지지 않고 foreground로 동작합니다.

하지만 이것은 nginx가 실행되었을때 background로 빠져버러 docker process가 바로 종료되는 문제를 해결할 뿐입니다. 실행시 nginx를 start 시켜주지는 못합니다. 그래서 저는 Dockerfile을 통해서 nginx를 실행하는 Image를 만듭니다.

우선 Dockerfile 이름으로 파일을 생성합니다. 그리고 그안에 아래의 내용을 넣습니다.

FROM nurinamu:gdg:basic
ENV PATH /path/to/tomcat9/bin
EXPOSE 80
CMD startup.sh && nginx

위와 같이 저장하고 아래 명령으로 build 합니다.

$ docker build . -t nurinamu/gdg:local

그러면 nurinamu/gdg:local 이미지가 만들어지게 됩니다.

해당 이미지를 실행하면 브라우저를 통해 http:localhost에서 톰캣 웰컴페이지를 볼 수 있습니다.

#이미지 실행
$ docker run -d -p 80:80 nurinamu/gdg:local

로컬 개발 Directory를 컨테이너에 연동하기

이제 웹사이트 개발을 해야하는데 매번 github에 올리고 컨테이너에서 pull하고 하는 불편한 방법으로는 무리가 있습니다. Docker는 local의 filesystem을 container filesystem으로 mount해주는 기능이 있습니다. 아래의 명령처럼 이미지를 실행하시면 됩니다.

docker run -d -p 80:80 -v {local dir}:{container dir} nurinamu/gdg:local

위와 같이 실행하면 container안에서 {continer dir} 접근시 {local dir}로 설정한 local 파일들을 볼 수 있습니다.

원하는 이미지를 만들 수 있게되었으니 이걸 나중에는 Google Container Registry에 올려둡니다.

다음 글에서 이제 GKE를 이용한 처리를 이야기해보겠습니다.

---------------------------------------- "Google Container Engine으로 서버 환경 구축해보기 1편" 끝 ----------------------------------------