항상 글을 쓸 때 잡다한 내용이 들어가서 길어지는 것 같긴 한데.. 막상 개요나 서론 같은 말을 하지 않으면 왜 어떻게? 이걸 공감할 수 있을까? 에 대한 생각이 길어지는 것 같습니다 즉 이번에도 잡설을 하나 하고 시작할 것인데 그 내용은 왜 수 많은 컴퓨터 언어 중 코틀린을 알아야 하지? 이런 질문을 해보고 싶어서 입니다

최근에 흥미로운 유투브 영상을 우연히 보게 되었는데요. 포프TV 라고 약간 인프런 유명 강사 백기선 풍의 자신감 넘치는 어투??로 어느 정도의 안티도 가지고 있는 프로그래머입니다

결론적으로 Managed Language 와 Unmanaged Language 두 가지를 각각의 무기로 가져야 한다가 주장입니다.

조금 더 자의적인 해석을 해보자면 사용하기 쉬운 언어에 빠져 메모리 관리를 이해하지 못한 상태에서는 다른 프로그래머가 만들어준 메모리 관리해 주는 부분에서 성능이나 비효율적인 문제 상황이 생겼을 때 이 부분을 이해할 수 없다는 부분입니다. 여기서 다른 프로그래머란 1000명 중 10명 즉 1% 프로그래머를 얘기 합니다

Managed Language 는 나머지 프로그래머를 위해 쓰입니다 즉 자동으로 쉽게 처리하는 방법은 없을까? 어떻게 하면 우리 조직의 프로그래머들이 실수를 없애고 많은 사람들이 쉽게 Best Practice를 모두 공유할 수 있을까? 이런 관점에서 100명(위의 10명 포함) 정도의 숙련된 프로그래머가 나머지 900명의 프로그래머를 이끌고 나가기 위해서 Managed Language를 가지고 실제 산업에서 개발일을 하게 됩니다

그리고 가끔 이런걸 물어보는 사람이 있는데요 "비 전공에 무 경험인데 개발일을 하고 싶은데 요즘 파이썬 이라는 언어가 유망하고 쉽다는 데 파이썬을 배우면 되나요?" 라는 질문입니다 여기에 답변을 해보자면

데이터 분석 관련 일을 할것이 아니고 코드량이 적다는 건 내부에 너가 이해하기 힘든 함축적인 일이 있다는 건데 문학으로 얘기하면 소설과 시의 차이인 것 처럼 그리고 어플리케이션 개발일이라면 전통적으로 Java 라는 것이 특히 웹 분야에서 많이 쓰이더라 근데 경험상 Java 랑 비슷하고 좀 더 간단하게 작성하고 다양한 기능이 있는 C# 이라는 언어가 차라리 쌩 초보가 도전정신으로 배워보기 더 쉬운 언어인것 같아

"자바는 인도네시아 섬도 있고 커피로도 주위에서 많이 들어봤는데 C#은 처음 들어보는데 이걸 배우면 취업이나 써먹어 볼 곳이 있을까요?"

그러면 Java 처럼 JVM 기반이고 Java 보다는 C# 이랑 유사성이 많은 Kotlin 으로 첫 프로그래밍 언어를 해보는건 어때?(하지만 프로그래머스나 기타 등등 입사를 위한 코딩 테스트 플랫폼에서 지원 안되는 부분은 함정...)

이 마지막 말을 해보려고 위의 주저리 주저리를 하게 된 것 같네요

사실 과거에 Jump To Python 이라는 아주 기본적인 책만 읽어본 저의 생각으로는 와 이 언어를 내가 이해할 수 있을까? 왜 이게 이렇게 동작되지? 란 혼돈속에 그 이후 파이썬은 접었었습니다 물론 그때는 단순한 HTML의 DIV 를 비롯해서 모든 컴퓨터 언어가 이해가 안되기도 했지만요

다만 매번 새로운 패러다임과 새로운 기술들과 싸워야 하는 프로그래머라는 집단의 특성상 코틀린은 Managed Language 중에서 앞으로 점점 더 많이 쓰이게 될 것이고 최소 JVM 부분을 일단 제외하고 본다면 프로그래밍 입문자가 도전 해볼 가치가 있는 컴퓨터 언어라고 생각되는 부분에서 24시간 정도는 투자해 볼 하지 않을까?

그래서 몇 개 컨텐츠를 올려봅니다

먼저 입문 하는 영상으로 노마드 코더라는 니콜라스라는 유튜버가 올린 내용입니다

약 6분 정도 내용으로 문법이나 내부 동작에 대해서는 큰 관심이 없고 내 인생에 코틀린은 없다면 이 내용만 봐도 무방할 것 같습니다

아래는 입문 내용 부터 여러 장/단점 부터 실제 예제 코드 까지 있는 내용입니다 현재 코틀린 버전은 1.6.0 으로 변화가 조금 있을 수 있습니다. 목록은 시간 순서 기반이지만 맛의 종류에 따라 분류 했습니다

순한맛 내용을 쭉 보시면 24시간 내에 코틀린의 기본 문법이나 사용법은 어느 정도 눈에 들어올 것으로 보입니다. 특히 배달의 민족은 완성형에 가까운 예제 코드도 제공합니다

vaadin-spring-boot-starter 이라는 요상한 Front Library를 쓰는 것도 그렇고 JPA 상에 연관관계 자체가 없습니다

ManyToOne or OneToMany 와 같은 관계가 없는 것인데 뱅크샐러드에 근무 했던 지인도 조직마다 다르지만 본인도 JPA 연관관계 없이 사용했다고 했습니다

제가 예상 하기로는 대부분의 로직을 DB 트랜잭션 하에 코드로 구현 했을 것이고 비즈니스 처리를 우선적으로 보고 DB의 제약을 회피하고자 성능적인 이점 하에 FK 를 옵션적으로 배제하지 않았을까 생각됩니다

아무튼 Best Practice 는 아니어도 완성형에 가까운 예제로 보면 좋을 것 같습니다

사실 코틀린에 대한 세세한 내용 즉 예를 들면 저의 경우는 2가지가 매우 인상 깊었는데

1. Default Final Class

자바는 Default open 클래스이기 때문에 너와 내가 모든 관계에서 is 관계 상속 즉 extends를 하는 것이 무리가 없으나 kotlin은 Default 는 final로 open 키워드를 사용하지 않으면 기본적으로 상속이 되지 않습니다

매운맛 쪽에 관련 내용이 있고 제 생각으로는 상속으로 인한 복잡한 관계를 피하고 불변 클래스로서 취급했을 때의 변경을 막아버릴 수 있는 부분이 위에서 잠시 언급한 900명의 보통 개발자들이 실수할 여지를 막을 수 있는 부분으로서 생각됩니다(추가정보: Kotlin 디폴트가 final인 이유)

상속이라는 개념은 자신있을 때 써야 할 것 같습니다

2. Null Safe(추가정보 : Null References: The Billion Dollar Mistake)

뭔가 할말은 많지만 할말하않 해야 할 것 같은 Null 과 관련된 부분 입니다 (Null Exception은 우리가 Web App에서는 단순히 예외를 뱉고 끝나지만 다른 플랫폼(Desktop App)에서는 Error 이고 고치지 못하면 시스템을 폐기해야 하는 심각한 Bug 입니다)

Null Pointer 개념을 창시한 토니 호어 란 사람도 10억(이상으로 봐야할 듯)달러의 가까운 실수 라고 인정한 것 처럼 null에 대한 대응을 할 수 없는 상황에서는 수 많은 방어 코드들을 생산해야 할 것입니다

Null Safe 라고 하는 부분은 Null 이 없는 것이 아니라 Null 에 대한 방어를 " ? or ?: " 나 기타 등등 기본 기능으로 대응하기 쉽다고 생각하시면 됩니다 (공격에 대한 방패 장착)

이 부분도 Final 과 비슷한 느낌인데 상속처럼 null 을 관리하거나 제어할 자신이 없다면 함부로 도입 하기가 어렵고 비즈니스 상에 필요하다고 얘기할 순 있겠지만 이것을 쉽게 허용하면서 제일 중요한 Model 설계에 있어 null 을 무분별하게 추가할 여지를 주었고 운영/유지보수에 있어 속성추가나 수정에 있어 더 신중함을 들여 Model을 관리해야 하지만 null 을 만만하게 봐서 개발자가 필수 값에 대한 실수를 덜할 여지를 없애지 않았나 생각됩니다

즉 모델이 변경된다는 것은 우리가 적절하게 수정을 하는 것이 맞는가? 에 대한 질문을 할 수 있는 기회를 단순히 기능 구현에 치중해 넘어갈 여지를 주지 않았는가에 대한 부분입니다

새로운 속성이 추가된다는 것은 이것을 왜 추가해야하는지에 대한 타당성과 적합간 값의 Range 에 대해 생각하는 것이지 이 속성 추가해서 if( exist ) A else B 이렇게 구현 하면 5분만에 일이 끝나 이런 의도가 아니라고 보입니다

어쨌든 null 에 대한 방패가 있으니 그 방패를 잘 사용하면 되고 좀 더 궁극적으로 내가 후처리가 필요한 null을 왜 생산했는가를 한번 더 고민하고 사용했음 좋겠습니다

이 두가지에 대한 부분은 지난번 글에서 잠깐 언급 했었고 이건 꼭 봤으면 한다는 특징을 몇개 뽑아보자면 (진짜 특징적인 것만)

  • Familiar Syntax(like C#, Swift)
    • why C# no Java?

  • Bad?
    • No Static -> Companion Object { }
      • 단 한개만 만들 수 있다
      • static 이 없는 대신 사용할 수 있는 기능으로 static 으로 메모리에 올라가는 것이 싫었을까? 라는 생각이 든다 즉 개발자가 메모리상에 무분별하게 만들 수 있는 static 을 원천 차단해서 그 대신 object 로 생성하고 사용할 수 있는 비슷한 기능을 넣었나 싶다

한가지 개념만 더 추가하자면 Kotlin in Action 에 있는 내용인데 kotlin 에서 if, when, try 과 같은 부분이 java 에서는 문이라고 불렀는데 kotlin 에서는 식이다 즉 if 문이 아니라 if 식 try 식이라는 것입니다

영어로는 문(statement) 과 식(expression) 이라고 하는데 간단히 생각하면 문은 return을 해서 값을 반환하지만 식은 returen 없이 값을 반환할 수 있다 즉 제어구조가 기존의 함수 형태에서는 return 과 같은 문의 반환이 필수로 꼭 필요했지만 코틀린에서는 for 문을 제외하고 식으로 동작되기 때문에 코드 생김새가 좀 더 Readable 하게 return 없이 코드 표현이 더 깔끔 해 보이는 부분이 장점으로 보입니다

fun max(val a: Int, val b: Int) Int = if(a > b) a else b
fun max(val a: Int, val b: Int) Int {
   return if (a > b) a else b
}

위 내용 정도면 코프링을 위한 코틀린 기본에 꽤 접근했을 것으로 생각됩니다

코프링은 코틀린으로 작성된 스프링 웹 프레임워크 입니다 즉 기존에 스프링을 똑같이 쓰면 됩니다

다만 약간은 제목과 벗어날 수 있지만 Java 에서 Kotlin을 왜 해야 하지에 대한 선택이 아닌 필수로 봐야 하는 요소는 결국 이것이 아닐까? 에 대한 부분입니다

(대용량 데이터와 트래픽을 다루는)Backend 개발자의 생존과 관련있는 내용입니다

이 부분은 매운맛의 영상에 나온 워딩 그대로 적어보겠습니다

Coroutine (like fiber(C#), Go(goroutine))

  • Async/Non-Blocking System
  • Lightweight Thread

아래와 같은 부분이 가능합니다

  1. 협력형 멀티 태스킹
  2. 동시성 프로그래밍 지원
  3. 비동기 처리를 쉽게 도와줌

 

"비동기를 안쓰면 저희는 서비스가 안될 정도이기 때문에 갈아타게 되었다. 작년(2017년도)에 갈아 탔고 저희도 그렇게 빠른건 아니다"

"처음에는 Java 기반에서 Callback Hell을 만들었고 Java8 에서 CompletableFuture를 사용했고 RxJava도 있지만 어렵고 성능적으로도 좋지 않았다(1 기준으로)" --> Java Async is shit!

async Task<String> work() {
   Thread.sleep(200);
   return "done";
}
async Task moreWork() {
   Console.WriteLine("work started");
   var str = await work();
   Console.WriteLine("work completed: {str}");
}

"C# 에서는 2005, 6년도 정도에 단지 Keyword 2개만 예약어로 등록해서 쉽게 구현했다"

"MS에서는 OS 내부 하위까지 컨트롤이 가능하기 때문에 언어 레벨까지 쉽게 지원이 가능하다"

"Kotlin 에서는 Java Spec으로 ByteCode 로 치환이 되야 하기 때문에 함수형으로 바꺼서 지원을 했다"

suspend fun work(): String {
   delay(200L)
   return "done"
}
fun moreWork(): Deferred<Uint> = async {
   println("work started")
   val str = work()
   println("work completed. $str")
}
runBlocking {
   moreWork().await()
}

"읽기도 쉽고 이해하기도 쉬워야 한다"

"go 에서는 go fun()을 만들면 비동기 코드가 쉽게 구현된다"

"지금 현재(2018년) 비동기를 가장 쉽게 할 수 있는 언어는 이 3가지 언어이다(C#, Kotlin, GO)"

"이제 앞으로는 throughput 을 높이기 위해 엄청난 고민을 해야 할때면 이 3가지 언어중에 하나를 선택하셔야 할 것 같습니다"

"Coroutine 10만건을 만들때 Lightweight Thread를 10만건으로 만드는 것이고 한 Thread 안에서 이것이 가능하다, 즉 Coroutine 을 10만개 만들 때 Thread 10만개를 만들지 않기 때문에 Thread 간에 Context Switching 에 의한 Overhead 가 발생되지 않는다"

 

비동기 프로그래밍을 아래와 같은 Message Platform 기반에서 사용할 수 있습니다

Spring boot 1(Spring MVC) VS Spring boot 2 (Spring WebFlux)로 테스트 결과를 비교해보면

"Latency 는 엄청 줄어들었고 TPS는 3배 정도 증가했다"

"여러분이 생각하기에 Reactive 도 해야하고 WebFlux 도 해야 하고 이상할 수 있는데 성능을 위해서는 아마 이쪽으로 다 넘어가야 할 것에요"

"WebFlux 쓰는데 Kotlin 으로 하면 더 편하게 쓸 수 있습니다"

아이러니 한 부분은 저희는 2021년도 겨우 JPA를 도입했는데 쿠팡의 경우 2018년도 JPA 탈출을 꿈꾸고 있습니다

"가장 핵심은 JPA를 제거하는 것 입니다"

"저희 같은 Bulk Data를 처리하는 곳에서는 JPA 가 적합하지 않다"

"오피스 툴이나 BackOffice, Group Ware 같은 곳에 JPA 가 좋다"

"1억 건씩 data가 흘러가는데 stateful 하게 가지고 있을 필요가 없고 상태가 보관될 필요가 없는 수억건의 data는 stateless 하게 빠르게 처리해야 한다"

마지막으로 아래와 같은 질문과 답변이 있었습니다

질문

  • "JDBC 드라이버를 사용할 때 Async 지원이 안되기 때문에 RDB를 연결 할 때 이 부분 처리는 어떻게 하나요?"

답변

  • "RDB를 쓰지 않는다 카우치베이스나 카산드라를 연결해서 사용한다(문제점)"
  • "C#과 비교해 보자면 직접 OS를 만들고 직접 DBMS를 만들기 때문에 2005년도에 MS-SQL과 비동기로 처리하는 방식을 만들어 냈다"
  • "제가 왜 여기에 감명을 받았나 하면 throughput 문제가 있어 비동기로 바꿔보니 4배이상의 성능 향상을 보았고 그때부터 저는 모든지 비동기 처리로 가야 한다고 생각하게 되었다"
  • "자바 진영으로 오니 JDBC에 발목이 잡혀 어쩔 수 없이 RDB에서는 문제가 있다"

여기서 더 고민해보는건 코프링 기초 학습을 이미 넘어간 것 같아 아래 한 줄로 정리해봅니다

Kotlin 기반에서 개발하는 것의 장점은 Reactive 프로그래밍과 Functional 프로그래밍이 가능하고 특히 비동기 처리 방법을 통해 대용량 데이터와 트래픽을 쉽게 처리할 수 있다. 이는 Backend 개발자가 겪을 수 있는 성능 문제를 해결하는 하나의 해법이 될 수 있다(하지만 쉬운 내용은 아니다)

지금 당장은 적어도 2018년도의 쿠팡보다는 적은 데이터와 트래픽이라면 차라리 오버엔지니어링을 하지 않고 정확한 처리와 에러가 발생되지 않는 시스템 구축에 우선 순위를 두는 것으로 정리해 볼 수는 있을 것 같습니다 다만 미리 준비해 둔다면 분명 Backend 쪽에 피가 되고 살이 될 수 있을 것 같습니다

 

+ Recent posts