Why Kotlin?

Why Kotlin?

지난 Kotlin 컨퍼런스에서 정말 Kotlin의 기능적으로 환상적인 이야기들과 젯브레인이 그리는 Kotlin에 대한 거대한 야망들을 들을 수 있었지만, 발표자들이 이구동성으로 이야기하는 why kotlin? 에 대한 이야기는 다들 Joyful, Fun Fun Fun 이었다. 한 마디로 즐겁다라는 것. 그래서 글을 써본다. 이 글을 보고 Kotlin을 쓰고 안쓰고는 상관없다. 우리에게 개발 언어란 어떤 존재이고 나는 왜 Kotlin을 사용하고, 많은 분들이 썼으면 좋겠다라고 생각하는지 이야기를 해보겠다. 마지막에 그래서 나에게 맞는 언어가 무엇인지 한 번 고민해보면 그거대로 좋은 타임킬링이 되지 않을까 생각한다.

그럼 이제 을 팔아보자.

이야기의 시작으로 나는 이제 개발자의 입장, 코드를 작성해가는 우리는 모두가 코드소설가라는 입장에서 이야기 해보려고 한다. 두 직업 모두 타이핑을 하고 창작의 고통을 가지는 점에서 비슷하니까 ㅋ

S/W Engineer, 소프트웨어 개발자인 우리는 입력 받은 Data다른 Data로 변경하고 관리하는 각종 작업, 즉 Data 입출력을 코드로 작성하는 일을 한다. 정말 다양한 형태와 목적을 가지는 Data는 우리가 작성하는 이야기의 소재가 되고 그 목적이 된다. Data를 이리 저리 다루고 그 인과관계, 서사시를 써나가는게 코딩이 된다.

우리는 직업이 코드쟁이, 즉 이야기꾼이다보니, 이야기를 잘 쓰고 싶어한다. 이야기를 잘 쓴다는 것은 결국 좋은 코드를 만든다는 것과 같다.

좋은 코드는 뭐라고 정의해야할까..

성능이 좋고 버그 없는 코드도 당연히 좋은 코드이지만, 오랜 경험 바탕의 내 라떼 발언을 하자면 여러명이 참여하는 프로젝트에서는 한 명이 작성하는 코드 보다 다양한 사람들이 만질 수 있는 코드, 유지보수 가능한 코드가 제일 좋은 코드라고 생각한다.

그래서 나에게 좋은 코드가 무어냐라고 한다면, 누가 보더라도 이해가 쉽고 어떤 이야기를 하려는지가 명확하게 나타나는 코드를 말한다.

나는 오랜 기간 java라는 언어를 사용해왔다. 사실 java를 처음 접한 것은 특별한 이유없이 처음 월급받게 해줄 수 있는 언어라서였다. 마치 소설가로 등단하려면 모두 경어체로 써야한다며, 나에게 글을 쓰려면 경어체로 써 라고 주입된 것 처럼. 내가 선택한 것이 아니라 주변의 권유로 사용하게 되었고. 그냥 그 문체를 잘 사용하는 법, 익숙해지는 법을 학습하며 오랜 기간 지내왔다. 연차가 쌓이고 다양한 경험을 해나가면서, 글쓰는데 다양한 문체가 있다는 것을 알았고 내가 쓸 이야기, 나의 이야기를 잘 풀어나갈 수 있을 것 같은 스타일의 언어가 Kotlin이 된 것이다. 이제서야 내가 처음 주도적으로 직접 선택한 언어인 것이다.

그래서 어떤점이? 왜?

Kotlin은 이야기를 더 즐겁고 이해하기 쉽게 만드는 장치가 많이 있다.

내가 좋아하는 이야기(코딩) 스타일은 체인형태로의 작성, 함수형의 형태로 작성하는 것이다. java에서 stream을 처음 써보고 빨리 모던 코딩 스타일을 써보고 싶었던 상태에 Kotlin의 Scope function들은 너무 맘에드는 기능들이었다. 내가 코드를 써내려가는데 막힘이 없이 줄줄 써내려가도 코드 이해도가 그렇게 떨어지지 않는 장점이 있다. 물론 체이닝을 너무 남발하면 그거 자체로 이해도가 떨어지기 때문에 적절하게 끊어서 사용해야하는데, 앞서 이야기했듯이 우리는 Data의 서사시를 쓰고 있기 때문에 독자가 그 이야기 흐름(컨텍스트)를 놓치지 않도록 잘 유지해야한다.

이에 필요한 장치가 내가 보기에는 Data 무결성 유지인데. Data가 막 바뀌거나, 그 상태가 보이지 않는 곳에서 바뀌거나 해버리면 이야기의 흐름이 끊어져 버리기 쉽다.이놈이 이놈이고 저놈이 저놈이고 이야기 속 등장인물들의 캐릭터가 휙휙 바뀌어버리면 이야기가 복잡해지고 독자가 읽다지쳐 떠나가게 된다. Kotlin은 한번 선언으로 무결성을 강제할 수 있고 유지할 수 있는 기능들이 있다. 코드 이해도를 더 높일 수 있게 도와주고, 함수형 프로그래밍 지원에 적극적이라 순수 함수 작성을 해나가기 편해서 Data의 State처리가 밖으로 드러나도록, 즉 함수의 역할 이해가 잘 되도록 설계할 수 있게 해준다.(왜 함수형 프로그래밍 작성이 좋은지는 why funtional matter? 참고)

그리고 Kotlin은 그 지긋지긋한 Null과 멀어질 수 있다. 이야기의 문맥을 잘라먹는 null check를 정말 많이많이 지울 수 있다, 그래서 스토리라인에 NPE의 불안감 따위는 없다. Null Safety 만세!!

Kotlin은 코드 라인수도 java보다 확연히 줄일 수 있어 내가 하고자하는 이야기를 한 눈에 들어올 수 있게 이야기를 쓸 수 있다.

마지막으로 이제는 Kotlin 이야기에서 뺴놓을 수 없는 코루틴도 좋은 코드 작성을 위한, 내가 이야기하는 글쓰기 관점으로 좋은 장치 중 하나라고 생각한다. 비동기 프로그래밍을 하는데 있어 가장 핫한 RX는 RX에 대한 기초 지식이 적은 독자들의 이해를 어렵게 만든다. 체이닝이란 관점에서는 정말 강력한 기능들을 제공하지만 그간 나에게 익숙했던 구조형 데이터들을 처리하는게 아니라 데이터 흐름을 이해하고 그 수많은 편의 함수들을 학습하는 시간이 필요하다(참고 - 비동기 프로그래밍 테크닉). 하지만 코루틴은 간단한 예약어의 추가만으로 기존 코드를 그대로 사용할 수 있어. 쉽게 이해하고 쉽게 비동기 프로그래밍을 할 수 있다. 화려한 미사어구로 보기에는 멋있지만 내용을 어렵게 만드느냐, 아니면 이해하기 쉽게 간결한 말로 이야기를 써내려가느냐의 관점에서, 성능을 떠나 코루틴이 더 나에게 좋은 코드 문법이라고 생각된다.

이 외에도 다양한 이유가 있지만 위의 장점이 내가 Kotlin을 선택한데 가장 큰 영향을 준 부분이라 할 수 있겠다.

Kotlin 쓰세요 두 번 쓰세요

내가 써내려가는 이야기(=코드)를 많은 사람들이 쉽게 공감하고, 이해할 수 있게하고, 내가 쓴 이야기를 모티브로 또 많은 이야기들이 파생되는 것을 상상하면 너무 즐겁다. 좋은 코드 작성을 위한 방법이 언어의 특징만으로 되는 것은 아니고 추가적인 패턴이나 경험의 부분도 크지만, 언어의 장치들도 무시할 수 없기에 Kotlin의 언어적 장치는 내가 글쓰기 편하게 하고 타이핑을 즐겁게 할거라 생각한다. 즐거운 마음으로 만들어야 내가 전달하는 내용도 즐거운 결과를 만들어 낼 수 있지 않을까?

Kotlin은 아직도 계속 발전 중이기에 코드로 이야기를 써내려가는 많은 개발자분들이 나에게 맞는 방식은 무엇이지 라고 고민할 때, 나는 감히 Kotlin을 추천한다.

즐겁게 쓰자 Kotlin. 즐거운 개발 생활을 위해.

여기까지 Kotlin 헌정 팬레터겸 홍보 였습니다. :-)

---------------------------------------- "Why Kotlin?" 끝 ----------------------------------------
갑자기 유투브 관련한 감상

유투브. 너튜브. 너를 통해 나를 알게되

재택기간이 길어지면서 업무 집중에 조금 느슨해지거나 쉬고 싶을 때 가장 많이 애용하는 것이 유투브 시청. 어느 순가 이 마성의 유툽 알고리즘 세계에 빠져서 구독 채널 수가 200개를 넘겼다. 구독 채널도 많고 액티브 채널이 많다보니 하루 하루 새로 쏟아지는 컨텐츠들이 엄청나다. 그래도 시간은 한정적이기에 좀 걸러서 보게되는데, 이것들을 정리하다 보니 내 취향이 찾아진다 ㅋ

취향 찾기 위한 내 근래 채널과 키워드 상황

요새 많이 보는 구독채널

  • TWICE : 무조건 매일 기본 뮤비 감상 (Daily Batch임)
  • 덤덤_스튜디오 : 예리한 방에 나연이가 나와서 ㅋ
  • 맛있는_녀석들 : 먹방때문에 보다가 요새는 서브 컨텐츠인 운동뚱이랑 잡룡이십끼 때문에 많이 봄 ㅋ
  • 이거해조_원희형 : 조원희 처음에는 슛포러브랑 여기저기 나오다 자기채널 열었는데, 응원해주고 싶은 사람. 가야대 가야대 ㅋ. 세계 최초 은퇴형 축구 선수 (은퇴 후 몸이 더 좋아짐 ㅋ)
  • 피지컬갤러리 : 김계란 말이 필요없음. 재미있고 컨텐츠 들이 유익함.
  • 딩고_뮤직 : 킬링벌스 컨텐츠가 너무 좋다. 요새 노동요 채널. 음악 자체로 접근되는 컨텐츠들이 많아서 진짜 좋다.
  • 놀면_뭐하니? : 라섹때부터 구독하다가 요새 다시 싹쓰리 때문에 ㅋ
  • 비보이의_세계일주 : 비보이인 브루스리의 채널. 오늘 세계여행 마지막회 했는데, 정보가 부족한 국가들의 모습들을 보는 재미. 나도 젊었으면 해보고 싶은 혼자여행 대리만족용 ㅋ. 요새는 방구석 춤선생 컨텐츠가 좋다
  • 오분순삭 : 무도의 향수 ㅋㅋ
  • 노홍철 : 아직 영상이 3개 뿐이고 구독하지 말라니까 구독하게됨 ㅋ. 이미 10만 구독자 넘김. 유툽 열심히하는 정준하의 소머리국밥은 아직 5만인데 ㅋㅋ 정준하 애도.
  • 정육왕 : 고기고기고기 침줄줄흘리는 채널. 고기 굽기 스킬도 구경하고 고기 고르는 법도 배우고 고기로 시작과 끝.
  • 단희TV : 부동산 재태크 관련 정보. 차분하게 설명해주는 팁들이 귀에 쏙쏙!!
  • 김한용의_MOCAR : 김한용기자의 차분하면서 엉뚱한 멘트들이 재미있다. 리뷰 자체는 좀 자본주의 편향적인 느낌이지만 그래도 유익한 점이 많음

요새 자주 찾는 키워드

  • 트와이스 - 무조건 ㅋ 이젠 안본 영상이 없지만 다시 봐도 좋음
  • BTS - BTS 뮤비들과 각종 리액션을 보면 멋있고 국뽕 주입됨
  • tesla - 테슬라 관련 리뷰와 정보 수집을 위해. 나도 곧? ㅋ
  • 김하온 - 고등래퍼2부터 예능까지 쭉 봄. 시작은 “트와이스 김하온” 영상 보고 누구지? 하고 찾아봤다가 실력에 ㄷㄷㄷ 그리고 딩고 뮤직에서 킬링벌스 듣고 우와
  • 세정 - 유툽 알고리즙이 이끌어준 키워드. 내 아이들 입덕 시작점 IOI때부터 근래 영상들 보니 역시 내 원픽. 노래들도 너무 좋구만

뜸해진 채널

#영국남자 #졸리 - 한국에 오지를 못하니 컨텐츠가 고갈되가는 듯. 안타깝다. 과거 영상만 가끔 봄. 내 최애 채널이었는데… #Loud_G - 김민아 아나운서 때문에 자주 보다가 요새 공영방송에서 이미지가 바뀌다 보니 아수라백작 처럼 두가지 캐릭이 왔다갔다하니 몰입감이 떨어져서 김민아 위주 컨테츠 방송은 재마가 떨어지고 있는 느낌. 그래도 이미지 바꾸고 온앤오프 정도의 캐릭터 딱 좋음. 라운드쥐는 이제 안녕. #카라큘라 - 우파TV보고 동정의 구독으로 시작했다가 열심히 하는 모습에 꾸준히 봐았음. 근데 컨텐츠가 너무 비슷해지면서 지루해져감… #야생마TV - 입이 거칠고 최강마초 캐릭터. 캐릭터가 특이해서 이상하게 자주들어가서 보다가. 마찬가지로 컨텐츠가 좀 거기서 거기라 잘 안들어가짐. #우파푸른하늘 - 슈퍼카리뷰 위주의 컨텐츠들과 마이너 차량 유투버들과 연계되서 돌고돌면 여기로 왔던 채널. 여기도 컨텐츠가 좀 지루해짐. #동네축구고수_동고 - 코로나 때문에 스페인에서 돌아온 이후에 조금 시들해짐.

내 채널 취향 분석

주로 팬심에 의한 트와이스 관련이 대부분이고, 연관으로 K pop 컨텐츠와 음악 관련 영상들이 많다. 그중 걸그룹 영상이 제일 많지만, 과거 힙찔이였던 관성 때문인지 좋은 힙합음악들도 하나 꽂히면 줄줄이 찾아보는 느낌. 그 다음은 예능 영상들 단순 예능도 많이 보지만 요새는 운동(헬창, 축구)+예능 영상위주로 보고 있다. 뭔가 운동을 직접 내가 해야하는데 대리 만족 하는 느낌..와이프가 싫어하겠다. 운동안하고 남이 운동하는걸 보고만 있다니.. 그래서 대강 순서는 아이돌 > 음악 > 운동예능 > 먹방 > 예능짤 > 자동차 > 재테크 인 듯.

내 홈 큐레이션을 처다보면서 드는 유툽 추천 알고리즘에 대한 잡생각

괜찮은 영상에서 구좋알 영상 이야기하면 아무 생각 없이 누르다 보니 내 구독 리스트가 너무 많아서 요새는 홈에 나오는게 구독채널 신규 영상때문에 나온건지 알고리즘 추천인지 알 수 없는 상황. 그래도 뇌피셜로 비중 나래비를 해보자면. 구독 채널 중 자주 가는 채널의 신규 영상 포함해 보지 않은 영상들이 제일 비중이 크고, 최근 본 영상과 관련된 것들이 그 다음, 그 중에서도 내가 보지 않은 영상들 위주로. 결국 내가 본 영상들은 홈에서 잘 안보이지만 관심사의 영상이 나오기 때문에 어디를 보다가도 다시 홈에 오면 볼게 넘친다. 재시청하고 싶은 컨텐츠는 검색이나 구독, 좋아요 누른 영상 등의 방법으로 접하게 하고 홈은 가능한 안본 영상으로 뿌려주는 것이 유툽에서 도망가지 못하게하는 방법인 듯. 넷플릭스는 아직 중복이나 이미 본게 너무 많이 홈에 나와서 그런 정도는 잘 안되고 인스타 검색 첫 화면도 중복이 많다. 그래서 그런지 넷플릭스는 막 신규로 보는게 별로 없다. 어쩌면 넷플릭스는 호흡이 긴 영상들이다보니, 가능한 내가 보는 영상의 신규 에피소드로만으로도 유지가 되는 듯. 근래에 내가 하는 업무가 컨텐츠 추천과 관련되서 그런지 추천 알고리즘이 관심이 많은데 알고리즘의 결정은 컨텐츠보다 해당 컨텐츠를 소비하는 사용자의 패턴과 회사가 원하는 사용자의 소비 패턴 위주로 만들어져야 승산이 있는 것 같다.

…나도?

갑자기 유투브를 보다가 채널이 많아져 쳐다보다 블로그 까지 남기게 되었는데 결국 뻘소리만 남기다 끝난다. 근데 자꾸 보다보니 blog 말고 vlog를 나도 시대에 맞춰 시작해봐야하는 것 아닐까 하는 생각이 든다. 컨텐츠를 정하고 시작하지 말고 그냥 기록차원의 vlog를 나도 해볼까?

---------------------------------------- "갑자기 유투브 관련한 감상" 끝 ----------------------------------------
학습은 개발자의 숙명.. 그렇다면 해야할 것은?

많다 많아 정말 많아. 가지를 좀 치자

푸념 중의 푸념. 요새 기술이 너무 쏟아진다. 진심으루다가 너무 많다. 근데 막상 현실에서 내가 일하는데 필요한 것들은 몇 가지 없다. 어쩌면 적용해보고자하는 확신이 들 정도로 학습되지 못한게 많기 때문일 수 있다. 학습은 개발자의 숙명이라지만 나이가 들며 학습 시간이 가족과의 시간으로 대체되면서 물리적으로 예전만 못하다. 예전에는 그래서 이것저것 다 기웃 거려볼 수 있었지만, 이제는 좀 선택과 집중을 해야할 시기이다. 그러면 어떤 기준으로 공부해야할까.

과거에 학습은 그냥 유행하는 것, 주변에서 버즈워드 될 만큼 많이 이야기되는 것 위주로 공부를 해왔던 것 같다. 한 마디로 트랜디한 기술들 위주로 공부했던 것 같다. 그러다 보니 정말 나에게 필요한 기술인지에 대한 고민없이 흘러왔다. 물론 주변인들에게 듣는 기술들은 아무래도 같이 업무가 겹치는 분들이라 그런지 또는 얻어 걸린건지 괜찮은 학습결과를 보이기도 했다. 문제는 전혀 쓸일도 없고 하면서 흥미도 가지지 못한 것들이다. 이런 것들은 뺴야한다. 결국 학습 결과가 좋은 경우는 학습하고 현업에 사용하게 되는 경우다. 그래서 내가 살고 있는 서버 개발자 필드안에서 사용될 만한 기술들로 일단 좁혀보자. 여전히 이 범위는 광범위하다. 개인적으로 학습은 미래지향적이 빠지지 않았으면 한다. 어차피 공부하는 것이라면 선수 학습을 해보고 싶은 욕심을 지우고 싶지는 않다. 남들 보다 더 아는 것에 대한 욕심은 나름 학습 동기부여도 되기 때문이다. 자 이제 할일은 대강 그려진다. 학습거리를 선정하기 위해 내가 살고 있는 서버기술 동네의 흐름을 한번 그려보고 그에 따라 내가 앞으로 사용하게될 것들에 대한 예상을 해보고 내 학습 기준을 만들어보자.

이 바닥 구른지 벌써…경험과 뇌피셜로 생각해보자

과거의 경험에서부터 현재의 경험까지를 돌이켜 보자면 예전 서버기술이라함은 웹페이지를 서빙하는 기술인 웹기술들이었는데, 이 시기에는 물리장비 하나에 프론트/백이 모두 포함된 작은 웹서비스들이 많았다. 트래픽이 많은 서버들 역시 장비를 많이 idc에 늘려서 트래픽을 감당했던 걸로 기억한다. 이후 ajax가 퍼지면서 front/back이 나눠지고 이것이 웹개발자를 프론트개발자, 백엔드개발자로 나뉘어지는 계기를 가져왔다. 이때 ajax, jaxb, soap, rest 등등 api 지원하는 기술들을 공부했고 이후 servlet으로 불편했던 여러가지 필요 라이브러리가 묶이며 spring이 나왔었다. 지금까지도 롱런하면 계속 학습하는 Spring만 보더라도 기술은 항상 필요에 의해 만들어졌다. 앞으로의 흐름에서 어떤 것들이 필요할 것 같고 그에 맞춰 나온 기술들을 찾아봐야겠다는 생각이 들었다.

클라우드의 시대로 넘어오고 서버 인스턴스의 관리 기술들이 복잡도를 가지면서,DEVOPS와 SRE란 영역이 서버개발자 영역에서 분리되기 시작했다. 서버기술이 점점 전문성이 강화되는 방향으로 가고 있고 난 어플리케이션 레벨의 서버개발이 좋기 때문에 SRE영역의 학습은 좀 가지를 쳐도 되겠다. 하지만 DEVOPS 영역의 빌드/배포 관련해서는 개발과 떨어지기 어렵기 떄문에 관련 지식은 계속 습득해야한다. 빅데이터 / ML 역시 서버 개발자들에게 하나의 영역으로 다가왔지만 이것 역시 전문영역으로 빠져나가면서 다 쫓아가기에는 무리가 있어 어플리케이션 개발시에 필요에 따라 학습해야겠다는 정도로 생각하고 가지를 치자.

클라우드 덕분에 서버의 복잡도를 늘리기 쉬워지면서 MSA가 나왔다. 이로 인해 복잡한 서버 연결도를 관리하는 기술들이 쏟아지고 MSA에 효율적인 서버 아키텍쳐들과 프로그래밍 기술들이 쏟아지는게 지금으로 느껴진다. MSA로 인해 하나의 서비스에서 관리하는 서버의 양이 늘어나면서 복잡도 뿐 아니라 당연히 늘어나는 것이 비용. 클라우드가 유동적인 리소스 관리를 해주지만 하나의 서버안에서의 효율성 증대는 다른 이야기다. 이로 인해 나오는 프로그래밍 기술이 비동기 프로그래밍. 결국 지금 내가 한동안 껴안고 가야할 학습 영역은 아래 처럼 나눠질 것 같다.

현 시대에 따른 나의 학습 카테고리

  • 숲의 영역 : MSA 아키텍처 관련 기술군
  • 나무의 영역 : Application의 성능 향상을 위한 기술
    • 비동기 프로그래밍 :
      • Reactive : RxXXX를 통한 대부분의 언어를 커버하는 디자인이 가능한 장점
      • Coroutine : Rx보다 러닝커브가 작고 리소스 효율성 측면에서는 더 나을 것 같다, 단 Kotlin만 가능. (Go도 가능..Go 를 공부해야할까..고민)
    • 함수형 프로그래밍 : 비동기 프로그래밍은 결국 Thread Safe이 중요하기 때문에 순수 함수 / Immutable이 중요한 FP가 대세가 될 것 같다
    • 서버 프로그래밍
      • Webflux : Rx, Coroutine 두 가지 다 해야할까. 이것도 선택과 집중이 필요.
    • 서버 개발자 교양
      • GraalVM : Java로 만들어진 Virtual Machine. GraalVM 사용으로 성능이 개선되었다는 글들이 종종 보여. 관심이 간다. Java로 만들어졌으니 코드도 구경하자

그래서..결론은

호기심에 접근했던 다른 것들 보다 일단 위의 내용들부터 내가 만족할만한 수준이 될 때 까지 공부하려고 한다. 그리고 나서 ML이나 React/Flutter 처럼 호기심에 접근하는 것들을 해야겠다. 시간을 효율적으로 사용하기 위해 선택과 집중!. 그래서 요새 계속 보고 있는 Webflux부터 끝내자.

MSA와 비동기 프로그래밍의 시대 뒤에는 뭐가 있을까? 아마 0/1 바이너리 시대를 끝장낼 양자 컴퓨팅 관련 기술들이 나오지 않을까 생각한다. ML을 내가 공부해야할 영역에서 분리해냈지만, 앞으로 대부분의 서비스들이 AI관련 서비스로 변경될 것 같다. 이에따라 서버에서는 실시간 학습, 피드백이 필요해질 것이고 결국 양자컴퓨팅 기술과 거기에 연관된 확률성 프로그래밍의 시대가 올 것 같다. 아마 다음에 다시 학습 리스트를 짠다면 요것들을 포함하게 되지 않을까?

재택근무를 하면서 뭔가 학습이 흐지부지 되는 경향이 있는데 채찍질겸, 블로그 심폐소생겸 혼잣말 쓰기 끝.

---------------------------------------- "학습은 개발자의 숙명.. 그렇다면 해야할 것은?" 끝 ----------------------------------------
Webflux 공부하자 1편

또 Webflux 공부?

지난 글을 쓰고 무려 1년 동안 제대로 보지 못하다가 다시 공부하면서 그 내용을 정리한다. 이전에는 정리 없이 우수수 글만 읽고 써보지를 않아 금방 잊었지만 이번에는 좀 더 부분부분 찾아서 이해하며 정리해보자.

Webflux와 Reactive Streams

Spring Webflux 문서를 보면 Reactive Stream에 대한 이야기가 나온다. 이 둘의 관계가 무엇인지 알아보자면, Spring의 Webflux에서 사용하는 reactive library가 Reactor이고 Reactor가 Reactive Streams의 구현체이다. 그래서 Webflux 문서에 Reactive Streams가 언급되는 것이고 그거와 같이 Reactor가 나오고 주요 객체인 Mono / Flux가 나오는 것이다. 결국 Webflux의 동작 구조를 이해하는 기본에는 Mono / Flux의 이해가 필요하고 그 이해를 위해 Reactive Streams에 대한 이해가 필요하다. 줄줄이 사탕이다.

Reactive Streams?

Reactive Streams 공식 문서에 정의된 문장을 그대로 본다면 Reactive Streams은 논블럭킹 백프레셔(non-blocking backpressure)를 통한 비동기 스트림 처리 표준을 제공하기 위한 명세이다. 이 영어같은 한국어에 대한 내용은 라인 엔지니어링 블로그에 너무나 잘 설명되어있다. 그 중 backpressure가 중요한 개념으로 이해가 꼭 필요하다. 이 철학적이면서 사명감을 가진 비동기 스트림 처리를 위한 명세는 의외로 매우 간단하게 4개로만 정의되어있다.

  • Publisher : 경계가 미확정된 순차적 데이터들을 생성하는 컴포넌트
    • Publisher는 Subscriber의 onNext호출 토탈 횟수는 반드시 Subscription의 request 횟수를 초과해서는 안된다. (#제1번 룰)
      • 이것이 어떻게 지켜지는지에 대해서는 실제로 코딩을 해보면서 확인해야할 것 같다.
  • Subscriber : 순차적 데이터를 받아서 처리하는 컴포넌트
    • onSubscriber -> onNext* -> (onError onComplete)? 순서로 시그널을 받게된다.
  • Subscription : Publisher에 의해 발행되는 구독 정보 컴포넌트
    • request에 의해 backpressure가 가능.
  • Processor : Publisher/Subscriber Stream의 미들웨어. Publisher이면서 Subscriber

기본적인 Observable 패턴과 유사해 이해가 어렵지 않다. 차이가 있다면 Subscription의 request메소드를 통해 backpressure 기능이 탑재되어 있다는 것이다. 탑재라기보다는 backpressure가 가능하게 interface가 있고 우리가 사용하게될 Reactor에서 구현이 되어있다. Reactive Streams 다 봤다. 참쉽죠잉(!?) 막말. 일단 넘어가자 갈길이 멀다.

Reactor

결국 원하는 것은 Webflux의 제대로된 이해를 통해 프로젝트에 적용 필요 기술인지 확인하고, 어떻게 잘 녹여낼 수 있을지를 알아내는 것이다. 그래서 그 코어기술인 Reactor를 들여다 본다. 참고자료에 링크된 튜토리얼 강좌를 따라해보자.

Flux / Mono

Reactor 관련된 여러 글들을 보면 Flux / Mono가 가장 중요한 컴포넌트로 나온다. Reactive Stream은 기본적으로 비동기 프로그래밍 표준을 목표로하고 있기 때문에 그 구현체인 Reactor는 비동기 지원을 위해 대부분 함수형 프로그래밍 형태로 구현이 되어있다. Mono / Flux를 처음 만났을때 FP의 Functor와 비슷하다고 생각들었다. 그래서 Reactor에서 FP의 향기가 진하게 난다.

  • Flux
    • 0..N 의 데이터를 만들어내는 Publisher, 생성데이터가 0개 또는 1개로 명확하게 구분되는 것은 Mono로 사용되어야한다.
    • Data의 흐름 단위, Complete / Error가 되기전까지는 무한 생성 가능한 Stream으로 생각해야함.
    • javadoc에 보면 모든 함수 동작들이 그림으로 설명되어있어 더욱 이해가 쉽다.
    • static 메소드는 소스 생성에 관련된 것들이고, instance 메소드들은 비동기 파이프라인 처리를 위한 것들로 구분되어있다.
    • 메소드가 너무 많기 때문에 나에게 필요한 것을 찾기위한 문서도 존재. 개발하면서 method 찾기 entry로 javadoc에서도 이걸로 접근하길 추천함
    • 주의할 점 : 기존 동기 코드에서는 애러처리가 try/catch 등으로 간단히 처리되었지만 비동기 코드에서의 애러처리는 Error event를 받아서 처리해야한다. 이게 데이터 흐름 중 애러가 발생하면 해당 Flux는 종료되는 것이기 때문에 이전에 받은 데이터들에 대한 처리등을 생각해야하기에 처음 설계시 애러처리도 정확히 고민되어야한다.
  • Mono
    • 0..1 의 데이터를 만들어내는 Publisher
    • 1개의 데이터를 처리하는 Flux를 Mono로 변경이 가능하고 Mono 역시 1개 초과로 처리시 Flux로 변경이 가능하다.

StepVerifier

StepVerifierreact-test에 포함된 테스트용 클래스다. 이것을 이용해서 Publisher가 우리가 원하는 형태로 동작하는지 테스트 가능하다. 지원되는 기능이 매우 다양한데 그 중에 가장 마음에 드는 것은 VirtualTimeScheduler 기능인데 이것을 이용하면 긴시간의 주기로 동작하는 Publisher를 주기변경해서 테스트 가능하다. 다시말해 하루에 한번 배치동작하는 것을 설정을 통해 시간을 무시하고 동작하게 해서 테스트 가능하다. 과거에 테스트를 위해 실제 코드에 주기 변경하는 코드를 넣고 테스트를 했었는데 그럴 필요가 없다!

Transform / Merge

개발자들이 하는 것은 결국 데이터를 입력 받고 원하는 형태로 전달하고 가공하는 것이다. 여기서 전달을 위한 입출력 pipeline은 구축이 되었고 이제 가공하는 것들이 필요하다. fp에서 자주 접하게되는 map/flatMap가 Mono/Flux에서 제공이 되고 merge, concat등의 merge operation도 제공이 된다.

Request

서두에 이야기했던 Reactor가 단순 pub/sub과 다른 점. 바로 요 backpressure 기능이다. Subscriber는 Publisher에게 현재 처리할 수 있는 data 갯수를 알려줘서 해당하는 만큼만 받아올 수 있다. 이것은 Subscriber의 부하가 몰리는 것을 방지할 수 있다.

Error

Reactor에서 Error 역시 Event로 Signal을 받아 처리가능하다. onErrorReturn, onErrorResume등의 메소드로 Error Signal을 받았을 때 처리하거나 propagate를 사용해 stream 내부 map에서 처리하던 것을 상위로 전달 할 수 도 있다.

techio 후기

아주 간단한 code snippet들을 짜보면서 기능들을 익히는 것에 도움이 되었고, 일부러 javadoc을 찾아보게 해주는 점이 좋았다. 하지만 방대한 api 중에 일부만 다루다보니 결국 Reactor적응을 위해서는 작업하면서 다양한 상황을 경험하며 함수들을 써봐야할 것 같다. 그리고 Flux, Mono javadoc에 나온 그림 기호들에 빨리 익숙해지는 것이 나중에 메소드 찾기에 도움이 될 것 같다. 이제 Reactor Tutorial이 끝났으니 Webflux로 돌아가보자.

참고자료

---------------------------------------- "Webflux 공부하자 1편" 끝 ----------------------------------------
OpenTracing? OpenTracing!

OpenTracing? 넌 누구니. 왜 필요하니.

이 글은 팀에 OpenTracing을 소개하기 위해 작성했던 글로 일부 내용 수정해서 블로그로 옮겨왔습니다. 

이제는 대부분 서비스들에게 분산 인프라 환경이 보편화되면서 복잡도를 가지게된 인프라 환경의 모니터링과 운영 이슈 처리에 관심을 많이 가진다. 그래서 분산 환경에서의 디버깅용 로깅을 어떻게 하면 좋을까 찾다가 알게된 OpenTracing에 대해 정리해보았다.

OpenTracing이란

이 공유에서 언급될 OpenTracingCNCF 산하의 프로젝트로 단어 그자체 처럼 하나의 흐름을 공개적으로 추적하기 위한 기능을 표준화하는 프로젝트입니다. 아직 공식적인 OpenTracing의 표준은 존재하지 않고 CNCF가 가장 큰 기구이기 떄문에 Cloud환경의 입김(question)이 쎄서 주목받는 비공인 표준 입니다. 현재 해당 OpenTracing spec을 기준으로 만들어지는 Tracer들로는 Zipkin, Jaeger, Lightstep등 다양하게 존재합니다. (CNCF사이트 supported tracer목록에 zipkin이 빠져있는건 왜 그런지 궁금하네요)

이제는 서비스를 운영하는 대부분의 서버 개발자들에게 MSA가 보편화되고 여러 효율성 관점에서 도입되고 있을 때, 이런 분산 환경의 로깅이 주목을 받으며 OpenTracing이 그 방안으로 나오고 있습니다. 사실 OpenTracing은 분산 환경의 로깅을 목적으로 만들어진 것이 아니고 하나의 request에서 response를 반환 할 때까지 거치는 서버의 연결 점들을 추적하기 위한 시스템으로 시작된 것이었습니다. 이 서버 연결을 추적하다보니 자연스럽게 해당 서버들의 req/res latency를 확인할 수 있게되어 bottleneck check가 가능하게 되고 그 서버 안의 로그까지 합쳐져 코드레벨의 디버깅도 할 수 있는 기능들도 들어가게되었습니다.

표준화를 시도하는 이유는 OpenTracing Big Piceces(위 그림)에도 설명되어있지만 OpenTracing이 표준화된다면 우리 서비스의 분산 로깅만 가능한 것이 아니라 우리 서비스에서 외부서비스로 연결시 최초 요청의 trace id로 연결되어 모든 연결 구조의 추적이 가능하게 됩니다. 예를 들어 빌링 서비스도 우리가와 모두 같은 tracer 기준으로 opentracing 을 설정한다면 장애발생시 좀 더 빠르게 확인이 가능하곘죠? :-)

왜 OpenTracing을 갑자기?

현재 (회사)팀의 환경에서 운영중인 서버가 단일 서버군을 참조하는 것이 아니고 요청에 따라 복수개의 서버군을 거치게 됩니다. 이럴 때 서버간 로그가 통합관리되는 것이 아니라 문제에 대한 디버깅시 로그를 각자 찾거나 bottleneck을 찾기하는 활동을 할때 각 서버의 로그들을 따로 뒤져봐야하는 불편함이 있습니다. 거기에다 각 서버별 로그를 연결된 reqeust/response를 찾아서 보는 것이 정말 쉽지 않은 일입니다. 앞으로 팀에서 관리하는 서버군의 복잡도가 올라가고 분산 환경이 더 커지게 될 수록 디버깅 작업의 난이도가 올라가고 개발자의 피로도가 올라갈 것이 예상되기 때문에 이러한 작업이 진행되면 차후 편안한 디버깅 생활을 할 수 있을 것 같아 도입검토가 필요합니다. 물론 디버깅할 일이 없게 코딩을 잘하면 좋겠지만 현실은….ㅋ. 최근 팀에서 검토중인 istio가 팀에 녹아들거나 한다면 더욱 편하게 OpenTracing환경을 도입할 수 있게됩니다.

OpenTracing Overview

OpenTracing spec에 대해서 간단하게 오버뷰를 해봅니다. 우선 OpenTracing에서 사용하는 Data Model들을 먼저 이해하면 관련 문서를 참조시 도움이 될거라 간단하게 짚어봅니다.

  • Span
    • OpenTracing Data Model의 기초 단위로 시작과 끝을 가지는 Timeline block입니다. 다시 말해 시간을 측정하게되는 모든 단위를 뜻 합니다. 시간을 측정한다는 것은 측정 시작 지점과 종료 지점이 있으니 그것이 하나의 Span이 됩니다. Span은 Parent / Child 구조를 가지고 있는데 이것은 우리가 흔히알고있는 Tree Node의 Parent Child와는 조금 다르게 하나의 Span을 세부로 나누었을 때의 전체가 Parent, 하부에 포함되어있는 Span이 Child Span이 됩니다. 예를 들어 하나의 api reqeust/response가 하나의 Span이라면 그 reqeust를 처리하는 내부 코드 method call 하나하나를 Span으로 생성시 method Span은 Child Span이 됩니다.
    • Span은 하위의 attribute들을 들고 다닙니다.
      • Operation Name
      • start / finish timestamp
      • Tags
        • key/value 구조의 사용자정의 필터 값들
      • Logs
        • key/value 구조의 정보 메세지
      • SpanContext
        • 각 Tracing 구현체에 따라 달라지는 내용. 기본적으로 trace id와 span id등이 포함됩니다.
  • Tracer
    • 위 Span들에게 특정 id를 부여하여 발송하고 저장하는 시스템을 말합니다. Zipkin, Jaeger 와 같은 것들을 지칭합니다.

동작 원리

동작 원리는 의외로 간단합니다. 위에서 설명한 Span단위의 정보들을 특정 Storage서버에 전달하면 해당 시스템은 그 Span들을 Trace ID, Span ID별로 Timestamp 정렬하게 됩니다. Tracer 별로 SpanContext 구조나 형태가 다를 수 있어 Tracer별로 서로 Span을 공유하지는 못하고 컨버터들이 존재는 합니다

Zipkin Example Flow - https://zipkin.io/pages/architecture.html

OepnTracing을 통해 우리팀이 얻을 수 있는 것

  • 위에서도 언급하였지만 결국 빠른 이슈 원인 파악이 최고의 장점입니다. OpenTracing은 단순히 reqeust/response network 연결에 대한 것만 추적이 가능한 것이 아니라 Redis / MySql 과 같은 외부 캐싱서비스나 데이터베이스의 연결 까지도 추적할 수 있어 문제가 발생한 호툴이 어디까지 진입하였고 어디에서 문제가 발생하였는지 빠르게 확인 가능하게 됩니다. 장애 발생시 로그 수집 서버에 Trace ID만 찍어주면 불편하게 키바나에서 이리저리 쿼리 날리면서 로그 찾기 안해도 됩니다.
  • 팀에서 OpenTracing의 성숙도를 올리고 다른 팀에 전파가 가능하다면 타팀과의 api 협업시 이슈 해결에 더더욱 효과적이 될 것입니다. 이슈에 대한 해결 능력이 좋아지면 서로서로 윈윈이겠죠?

OpenTracing을 통해 해야할 일

이렇게 좋은 것을 왜 이제야! 그리고 왜 다른 곳은 안하지? 에 대해 고민해보면 답은 사실 간단합니다. 인프라 구조가 복잡도 + 디버깅의 어려움 vs 환경 구성에 대한 불편함 의 내적 대결 구조가 있기 때문입니다. OpenTracing 환경 구성을 위해서는 처음 설정에 노오오오력이 들어갑니다. 세상에 쉬운일은 없습니다. 하지만 조금 노오오오오력 해서 구성하면 후세에 편안함이 올거라 생각됩니다. 그래서 할일을 나열해보면…

  • OpenTracing 기술 스택 선정 - Tracer 선정
  • Tracer Server 설치
  • 각 서버군별 적합한 Tracer Library 설치 / 설정 - Spring인 경우 Sleuth + Sl4j로 떙이지만… play+jdk7, ruby..는..;;; 좀 더 찾아봐야함.

---------------------------------------- "OpenTracing? OpenTracing!" 끝 ----------------------------------------