축구와 소프트웨어 개발

요즘 많은 개발은 팀 개발이다.

컨텐츠 단위로 나누던, 모듈 단위로 나누던, 서비스 단위로 나누던 어떻게든 협업을 해야하고, 나뉘어진 일을 누가 어떻게 가져갈 것인가도 매우 중요한 문제다.

사람마다 선호하는 것이 다르다.

어떤 사람은 컨텐츠 개발을 좋아하고, 또 다른 사람은 라이브러리 개발, 툴 개발을 좋아한다.

이걸 축구로 비유하면, 사람 마다 다른 포지션 (공격수, 수비수, 미드필더)를 선호한다.

멀티플레이어가 분명히 있긴하지만 그런 사람은 특별 케이스로 봤을 때, 각자 주 포지션이냐 아니냐가 퍼포먼스와 모티베이션에서 굉장히 큰 차이를 준다.

축구 처럼 주전 11명과 대회 마다 각기 다른 교체 인원 수가 고정되어 있는 것은 아니지만, 해야만 하는 일과 잘 할 수 있는 일, 그리고 하고 싶어하는 일의 밸런스는 무척 중요하다.

주전 경쟁에서 밀려서, 자기 포지션에서 뛰지 못해서, 감독의 생각과 자신의 축구 관이 달라서, 팀 성적이 좋지 않아서 등등 여러가지 이유로 선수들은 이적을 결심한다.

마찬가지로 개발팀도 팀원들에게 동기부여를, 성취감을, 만족도를 줄 필요가 있다.


팀의 철학과 전술에 따라 다르지만, 어떠한 팀은, 또 어떠한 감독은 궂은 일을 할 선수가 필요한 경우가 있다.

소프트웨어 개발도 비슷하게, 굳은 일을 도맡아서 해주는 선수가 있어야 팀이 매끄럽게 운영된다는 사실을 알고 있다.

많은 소프트웨어 에세이나 블로그 등에서 볼 수 있듯, 이 포지션을 주로 관리자에게 할당함으로써 문제를 해결하곤 한다.

하지만 흔히 궂은 일이라 불리우는 일 들을 즐기는 사람들도 있으며, 어떤 일이 궂은일이라고 생각되는 범주도 개인마다 다르기에 적합한 사람을 배치하는 것은 여러모로 의미가 크다.

리더의 역할중 하나를 덜어줌으로써, 다른 부분에서 리더의 영향력과 기량을 보일 수 있는 계기가 될 수도 있기 때문이다.

이에 대한 자세한 이야기는 관리자에 대한 이야기에서 다시금 이어가겠다.


구성원 중에 궂은 일을 해주는 동료가 있고, 그가 하는 일이 팀에 얼마나 긍정적인 영향을 끼치고 의미가 큰 일인지 공감대를 형성 할 수 있다면, 그 것으로 추가적인 부가 효과를 얻을 수 있다.

필요는 하지만, 선뜻 나서지 않는 빌드 마스터라는 업무가 있었는데, 이 업무를 번갈아서 진행하는 팀이 있었다.

그 팀에서 그 일을 하는 날은 평소 업무가 아닌, 빌드를 챙기고, 업무 관리 시스템 일감 관리, 문서화 보강 등의 작업을 진행하게 했는데, 이게 얼마나 번거로운 일인지 모두가 깨닫는 계기가 됐다.

그 후 해당 업무에 비중을 좀 더 크게 둔 팀원이 생기자, 팀에선 모두 그를 고마워했고, 그의 업무에 도움이 되는 일들 (문서화나 일감 관리)를 좀 더 신경써서 하게 됐다.

물론 이는 긍정적인 효과였던 사례중 하나 일 뿐이지만, 그 일을 하는 사람이 만족한다면 그것만으로도 가치는 크다.


또 의외로 많이 느낀 것은, 개발을 축구로 비유하면 패스를 하지 않는 선수가 꽤 많았다.

소통과 협업에서 큰 리스크를 가졌으나, 개인 플레이에 최적화 되어있어 결과물이 좋은 경우도 있다.

이 경우, 이 사람의 작업을 분석하거나 재작업 해야 될 때 코드 작성에서 마저 독특한 취향을 띄는 경우가 있었고, 연동을 해야 할 때 문제가 생기는 경우가 생기곤 한다.

이런 사람을 협업이 어려운 개발자 내지는 커뮤니케이션 역량 부족로 모는 경향이 있는데, 나는 이런 사람마저도 개발 기량이 기준 이상이라면 선택적 업무 할당으로, 협업 할 수 있다고 보는 입장이다.

물론 이런 사람에게 다른 사람과 다른 기대치와 잣대를 적용하는 것에 대한, 합의가 이루어져야 하는데 이 부분이 쉽지 않아 또다른 문제로 대두되기도 한다.

우리는 모두가 형평성 있게 대해지길 바란다.

그럼에도 누군가에게 예외가 적용 되는 것을 받아들일 수 하는 것도 팀과 관리자의 역할이다.

모든 부분에서 평균적인 재능을 가진 사람을 만나기란 무척이나 어렵다. 그런 인재는 모든 팀에서 원하기 때문이다.

개발자의 한 두가지 부분에서 아쉬움을 팀이 케어 할 수 있다면, 개발자가 부족하고, 최적합 인재는 더더욱 구하기 어려운 입장에서 대안이 될 수 있다.


이렇듯 직접적 협업을 하던, 간접적 협업을 하던 팀으로 혹은 한 회사에 묶여 있는 이상 영향을 작게나마 미칠 수 밖에 없다.

굳이 축구와 비유하지 않더라도, 여러 사람이 함께 해야 하는 모든 일들은 비슷한 상황을 여럿 맞이하게 될 것이다.

그럼에도 유독 소프트웨어 개발팀의 문제를 겪으면서 축구를 자주 떠올린 것은, 내가 축구를 좋아하기도 하고, 축구 팀들은 이런 문제를 오랜 시간 겪어오며 나름의 결론과 해결책을 가진 팀들이 좋은 성적을 냈기 때문이다.

여러 축구 감독/선수의 에세이 등에서 다뤄지는 축구 팀에 대한 이야기를 읽으며 꼭 한번 얘기하고 싶었던, 축구팀과 소프트웨어 개발 이야기였다.

(서평) 드리밍 인 코드 (Dreaming in code)

이 책은 로터스 1-2-3라는 전설적 프로젝트를 개발했던 케이퍼가 OSAF(Open Source Applications Foundation) 를 설립하고 챈들러라는 개인 정보 관리 프로젝트를 개발하며 겪은 일들을 다룬 책이다.

https://en.wikipedia.org/wiki/Chandler_(software)

챈들러 프로젝트는 순탄하기는 커녕, 두명이상의 프로젝트에서 있을 수 있는 많은 어려움을 다 겪었다.

그것도 훌륭하고 경험 있는 프로그래머들과, 풍부한 자금력을 기반으로 둔 회사에서 말이다.

작은 선택과 큰 선택 모두 최고의 결론을 내리기 위해 토의 시간이 길어졌고 프로젝트는 그만큼 지체됐다.

선행작업이 진행 되기전엔 속도가 붙지 않고, 선행 작업들에 대한 인사이트나 경험이 충분하지 못해, 빠르게 진행되지 못했다.

거기에다 업무 도구 마저 빈약하니 불만과 생산성이 급락했고, 그를 해결하기 위한 업무 도구 개발을 선행하고 만다.

프로젝트의 규모는 해야 할 일의 양에 따라 결정난다. 새로 작성해야 하거나, 결정 해야 되는 것이 많은 프로젝트가 (인원을 막론하고) 대규모 프로젝트가 될 수 있다.

첸들러 프로젝트가 겪은 문제들은 프로젝트의 규모에 상관없이 겪을 수 있는 문제를 비롯하여, 실력은 충분하다 하더라도 손발이 맞지 않는 개발자들이 모여서 작업 하는 일은 그리 쉽지 않다는 얘기를 비롯 수많은 교훈을 얻을 수 있었다.

워낙에 인상적인 구문이 많아 한 두 구문으로 정리 될 게 아니다보니, 아래에 문구들을 정리했다.


“우리가 직접 만들어서 사용합시다”란 의견이 나오면 긱들은 금새 들떠서 환호성을 지를것다 - P176

나도 그랬지.. 아니 아직도 좀 그런가?

MIT 캠퍼스에는 유명한 낙서가 있는데, “나는 프로그램만드는것보가 프로그램 작성에 도움이되는 프로그램을 더 좋아한다” - P176

내가 라이브러리 작업을 즐기고, 툴 개발을 선호하는 이유다. 나는 아직도 내 개인 작업에도 스크립팅을 비롯한 툴 작업을 좋아한다.


하지만 챈들러의 디자인이 지연됐던 또다른 이유는 디자인의 완성이란 곧 이상과 현실 사이의 고통스런 절충을 의미했기 때문이다. 최종 디자인없이 기술적 결정을 내리는 일은 힘들었고 기술 로드맵 없이 디자인을 완성하는 일 역시 어려웠다 - P185

닭이 먼저냐 달걀이 먼저냐는 어려운 문제이고, 실제로 이런 문제에서 정치로 이어지기도 해서 많은 생각이 들었다.

결과적으로 정답은 없다. 다만 빠른 프로토타이핑을 통해 우려 사항을 지워낸 쪽이 먼저 치고 나가 줘야 하는것 같다.


무엇보다도 OSAF는 앞으로 데드라인에 의한 릴리스는 하지 않을 계획이었다. 미래의 릴리스는 각각 몇 가지 기능들을 목표로 해서 모양새를 갖출 것이며 일정은 필요에 따라 변경될 (즉 늦춰질) 여지가 있었다. - P199

사실은 모든 개발 일정은 지키기 어렵다. 일정 완수에 근접하려 노력 할뿐. 그래서 버퍼가 필요하다. 사용자를 위한 일정과 내부 버퍼를 감안한 일정.


GTD(일을 깔끔하게 해치우기)의 주요 원칙 중 하나는 정기적으로 시스템에 등록된 모든 업무를 검토해서 다음에 할 일을 결정하는 것이다. p201

개발자들은 작업에 집중하려는 경향이 있기에, 주기적으로 이를 환기시켜주고, 누락된 일을 체크해야 될 필요가 있음을 말하는 것 같다.


리누스 토발즈 “자그마한 프로젝트를 시작하면서 그것이 거대해질 것이라고 기대해서도 안됩니다” 만약 그런담녀 설계에 지나치게 공을 들이게 되고 자신의 프로젝트가 실제보다 훨씬 더 중요하다고 생각하게 될 겁니다. 더 안 좋은 경우에는 스스로가 구상한 프로젝트의 규모에 겁을 먹고 포기할지도 모르죠. 그래서 작게 시작하고 구체적이고 세세한 부분을 고민하는 편이 좋습니다. 커다란 비전과 놀라운 디자인은 아예 꿈도 꾸지 말아야 합니다. 만약 당장 필요한 어떤 요구사항을 해결하지 못한다면, 분명히 설계가 지나친 걸 겁니다” - P211

“짧은 시간에 성공할 거라고 기대하지 마세요.” 그는 단호히 말했다. “저는 리눅스 개발을 13년째 하고 있습니다. 그리고 앞으로 한동안 계속 더 할 예정이고요. 만약 제가 그렇게 커다란 일을 해내려고 생각했다면, 아마 시작조차 못했을 겁니다. - P211

큰 목표보다는 작은 목표를 꾸준히 달성하는 것이 쉽다는 얘긴데, 격하게 공감한다.

좋은 관리자는 큰 일을 작게 쪼개서, 처리하기 쉽게 해준다.


챈들러 팀이 지난 일 년 동안 힘들여 개발한 진짜 데이터 저장소와 아키텍처를 가지고 더 이상 프로토타입이 아닌 실제의 인터페이스를 개발 할 수 있게 되자, 프로그래머들은 점차 개발에 욕심 내기 시작했다. 그들은 청사진과 구체적인 개발 명세서를 필요로 했다. - P218

바로 이 것이 좋은 리더와, 좋은 관리자가 필요한 이유라고 할 수 있을 것이다.

작업을 깊이 이해하고 있고 기술적인 레벨이 충분하지 않다면 청사진과 구체적 개발 명세서를 제대로 만들어 낼 수 없다.


사람들이 챈들러의 더딘 진전에 대해 회의를 표시하면, 케이퍼는 그의 올빼미 같은 눈썹을 치켜올리며 이런말을 내뱉었다. “저는 끈기를 빼면 아무것도 아니죠” - P251

실제로 케이퍼의 끈기가 아니었다면 이 프로젝트는 절대로 완수 될 수 없었다.

프로젝트에 대해 흔들리지 않는 뚝심을 보여줘야, 구성원들도 믿고 희망에 몸을 던질 수 있다.


“저는 현재 시점에서 ‘개밥 먹기’를 가능하게 만든다는 게 중요하다고 생각합니다. 가능하면 빨리 사용 가능한 소프트웨어를 내놓았으면 좋겠어요. 이를 반대하는 논리는 특정 시점에 별로 흥미롭지 않은 제품을 릴리스 하는 위험을 무릅써야 한다는 것 입니다. 하지만 ‘절반의 빵이 아무것도 없는 것보다는 낫다’고 생각합니다.” - P264

이것이 상시 빌드가 필요한 이유다. 개발 속도가 더뎌지더라도, 상시 빌드가 가능한 상태로 유지한 채로 협업 하는 것이 최종 완성도를 높게 유지하는 원동력이 되곤 한다.


그렇다고 하더라도 챈들러의 모든 기능을 구현하려면 시간이 많이 들거라고 두솔트는 대답했다. 개발 속도를 높이기 위해 할 수 있는 일은 그렇게 많지 않았다. 그리고 새 프로그래머를 너무 많이 투입한다면, 브룩스의 법칙이 작동하기 시작할 것이었다. - P265

물론이다. 개발에 속도가 안나는 이유는, 주로 문제가 복잡해졌기 때문이다.

문제를 단순하게 풀기 위한 노력은 다양하게 이뤄져야 한다.


“우리가 시도할 수 있는 한가지는,” 그녀가 제안했다. “포스트잇에 나눠 적는 거에요. 하나의 포스트잇이 대략 비슷한 작업량을 의미해야겠죠.” 포스트잇 종이 한 장에는 한 사람의 개발자가 한 달에서 두 달 정도 걸릴 작업 내용을 적어야 했다. 그들의 벽에 지금까지의 릴리스별로 포스트잇 종이를 정리할 계획이었다. 그러면 그들은 릴리스 때마다 계획한 내용과 그 계획에 현실적이었는지를 한눈에 볼 수 있을 것이다. - P274

화이트 보드 + 포스트잇! 트렐로를 통해 익숙한 스크럼 방식이다.

내 경험상 여타 업무 관리 시스템에 비해 직관적이고 쉽다.


성공적인 프로세스는 재사용될 수없다. 은총알은 재장전이 불가능하다. - P288

팀마다 문제가 미묘하게 다르거나 완전히 다르기 떄문에, 해결책은 팀마다 다를 수 밖에 없다.


TSP (Team Software Process)와 PSP (Personal Software Process)는 ‘독재적인 관리 스타일’을 지양하고 개별 프로그래머 들과 팀에게 계획, 품질 관리, 정보 공유, 그리고 업무 재분배에서 주도권을 돌려줌으로써, 자신들의 업무에 대한 통제력을 갖도록 장려하고 있다. 험프리는 한 발표에서 이를 다음과 같이 설명했다.

  • 우리는 모두 회사에서 일한다.
  • 회사는 일정 계획을 필요로 한다.
  • 당신이 재정적으로 자유롭지 않다면, 반드시 일정을 지켜 일해야 한다.
  • 당신 스스로 일정을 관리하지 않으면, 누군가 다른 사람이 당신의 일정을 관리하게 될 것이다.
  • 그렇게 되면 그 사람이 당신의 업무를 통제하게 된다.
  • P295

업무를 본인 스스로 관리하라는 의미다. 좋은 관리자가 필요하다는 얘기가 위에 많았지만, 사실 나도 하고 싶었던 말은 개발자 개개인도 자기 자신의 업무를 잘 관리하여 관리자와 시너지를 일으켜야 된다.


“우선 버그를 수정하시오”는 그럭저럭 그럴듯한 원칙이고, 대부분 개발자들은 적어도 이론적으로는 이에 동감을 표시할 것이다. 하지만 프로그래머의 의도가 어떻든 간에, 코드에는 항상 버그가 있기 마련이다. 소프트웨어 개발 과정에서 가장 널리 쓰이는 단어 중 하나를 차용해 설명하자면, 코드를 작성하는 과정은 ‘반복적’이기 때문이다. - P297

버그는 줄이려 노력하는 것이고, 빠르게 찾으려 노력하는 것이지 없앨 순 없다.

MS, Google, Apple, IBM 등 수 많은 기업들이 버그를 없애진 못했다.


결국 버그는 피해갈 수 없다. 개발중인 소프트웨어의 버그 목록을 훑어본다면, 심각한 버그에서부터 하찮은 것 까지 버그의 스펙트럼이 매우 넓다는 사실을 확인하게 될 것이다. 버그는 사용자를 성가시게 만드는 정도도 다르고, 버그를 발견하거나 수정하는데 드는 노력등에 있어서 커다란 편차를 보인다. 다시 말하면 모든 버그는 동등하지 않다. - P297

치명적인 버그를 미연에 방지하거나, 조기에 감지하거나, 얼마나 빨리 수정 할 수 있는가에 대한 문제다.

이를 위한 노력 비용도 동등하지 않게 하면 된다.

리스크가 큰 모듈이나 시스템 작업에 더 많은 코스트를 할당한다던지 말이다.


XP는 자칫 잘못하면 “쓰레기같은 결과물을 빨리 내놓는” 방법으로 전락 할 수 있다. - P305

XP의 방법론들은 오용의 여지가 많긴하다. 중요한 것은, 서로간의 신뢰를 잃지 않는 선에서 비효율을 제거하는 것이다.


스폴스키에 따르면, “방법론의 근본적인 문제는 방법론을 똑똑한 사람들이 만들어냈고, 이들이 사용할 때는 제대로 작동을 한다는 것입니다. 하라는 대로 지시만을 좇아가는 얼간이들이 이를 도입할 때는 제대로 작동하는 경우가 없죠. - P308

방법론은 만능약이 아니다. 실제로


37 시그널즈가 베이스 캠프 코드에서 레일스 프레임워크를 추출해낸 것 처럼, 그들은 베이스캠프를 만든 경험에서 애플리케이션 설계철학을 이끌어냈다. 이 철학은 다음과 같이 요약 될 수 있다. “더 적은 양의 소프트웨어” “새로운 기능 요구를 거절하는 것을 망설이지 마라.” “적임자를 찾아라.” “절반의 품질을 지닌 제품을 만드는 대신에, 절반의 기능을 갖추는 제품을 만들어라.” - P314

Rails가 훌륭한 소프트웨어일 수 있었던 이유라고 할 수 있다.

기능의 다양함 보다, 품질이 더 중요하다는 것을 사용자 일땐 매번 느끼지만, 개발자 일땐 종종 놓치는 것 같아 아쉽다.


마이크로소프트에 도전장을 내밀고 있는 구굴은 제이슨 프리드의 소프트웨어 개발 철학과 놀라울 정도로 비슷한 방식을 사용했다. 구글에서는 프로젝트 마다 소규모 팀을 순식간에 구성해 빠듯한 일정에 따라 업무를 진행하며, 비교적 지엽적인 문제를 해결하기 위한 웹 서비스를 내놓는다. 그러고 나서는 사용자 피드백과 서비스 운영 과정을 통해 점진적으로 서비스를 개선해 나간다. 또한 구글은 업무시간 중 20% 정도를 개인프로젝트에 사용할 것을 장려한다. 이런 ‘20% 시간’의 성과는 멋지고 새로운 서비스로 발전할지도 모른다. (아니어도 상관없고). “걱정하지 마세요” 구글은 직원들에게 이렇게 말한다. “그저 당신이 하고 싶었던 일을 해보세요!” - P315

서비스는 점진적 개선이 매우 중요하다. 한번에 다수의 사용자를 만족 시키는 것은 어려우며, 간단한 기능을 심플하게 제공 한 후, 피드백과 운영 과정에서 개선해나가는 것이 좋다는 것에 크게 공강한다.


리스프와 객체지향 전문가이자 썬 사의 “뛰어난 공학자”인 리처드 가브리엘은 주장한다. “저는 프로그래머들도 시인, 예술가처럼 창의적인 활동을 하는 사람들을 양성하는 방식으로 양성해야 한다고 생각합니다. 사람들은 이게 엉뚱한 소리라고 말할지도 모릅니다. 하지만 시문학 석사학위를 받으려고 교육받을 때 사람들은 무엇을 하나요? 그들은 위대한 시들을 공부합니다. 소프트웨어 공학에서 그렇게 하나요? 아니요, 우리는 위대한 소프트웨어의 소스코드를 읽지 않습니다. 위대한 소프트웨어의 설계를 공부하지도 않죠. 그 디자인을 보지도 않고요. 위대한 소프트웨어 디자이너들의 인생을 공부 하지도 않습니다. 즉 우리는 우리가 만들려는 것의 기존 문헌들을 공부하지 않습니다.” - P358

우리는 개발 경험을 공부하지 않는다. 선배들이 실패한 경험을 복기하고, 피해간다면 조금이라도 덜 실패할 수 있지 않을까?


결과적으로 기대한 것 이상을 얻어갈 수 있었던 책이다.

비슷한 문제를 겪고 있을 때 한번쯤 떠올려볼 조언 같은 느낌이었다.

이런 책 들을 통해 선배들로 부터 이런 조언들을 하나 둘 더 듣고 배우다보면, 확률 높은 성공적인 소프트웨어 개발에 대한 나름의 결론을 얻게 되지 않을까 기대해본다.

Java 적응기 03 - Akka

Java에서 또 인상적이었 던은 Actor 모델로 유명하고, Scala에서 더 유명한 Akka다.

Actor 모델의 근간은, 모든 통신을 Message로 하고, Actor 별로 단일 큐를 사용해 동시 접근 우려를 제거한다이다.

akka-internals

위는 Akka에 대한 간략한 설명을 그린 그림이다.

출처 : https://deepakpol.wordpress.com/2015/09/29/event-driven-and-reactive-architecture/

몇가지 주의 사항을 잘 지키면 손쉽게 비동기 프로그래밍을 할 수 있는데, 여기에서 또 중요한 점은 Actor 단위로 단일 큐를 사용하기 때문에 Actor 하나만 사용했을 땐 싱글 스레드 프로그래밍과 다를 바 없기에 워커를 돌리고 싶은 단위로 Actor를 사용 할 경우 적절하다.

또한 static 메소드나 메시지에 공유 자원으로 쓰일 수 있는 데이터를 던지고 그 데이터를 저장해서 사용할 시 동시 접근의 우려가 남아있다.

물론 이 점은 다른 멀티 스레드 로직 구현보다 훨씬 지키기 쉬운 규칙이기에 상대적으로 잇점이 큰 구현 방식이다.


나도 C++로 비동기 소켓 서버를 구현하면서, 메시징 기반으로 모든 로직을 동작 시킬 수 있다면 비동기로 동작한다는 것을 알고 그것을 구현해본 적도 있지만, 그 것을 규격화 하지는 않았다. 그리고 그 것이 Actor 모델이라 불리는 지도 몰랐고.

Akka는 메시징 기반 비동기 시스템을 규격화 하는데에 성공했고, 잘 정리되고 제약이 적게 구현되어 편리하게 쓸 수 있는 장점도 있었다.

실제 체감해보니 Java Akka의 장점은 실로 대단했다.

손쉽게 안정성 있는 비동기 프로그래밍을 진짜 할 수 있었다.

특히 개체 단위 lock을 사용했을 때처럼, 이 로직이 어떤 스레드에서 불려질 것인가를 고민 할 필요 없이 비동기 프로그래밍 할 수 있다는 것은 아주 큰 축복이다.

거기에 여러번 강조해도 모자라지 않는, 쉽고 제약이 적게 사용할 수 있게 구현되어있다.

안정성 확보는 덤이었다.


실제 팀에서 같이 사용 했을 때, 소통 코스트나 예외 처리 코스트가 급감했다는 점은 Akka (Actor Model)의 장점을 체감할 수 있었다.

다음 C++ 비동기 프로그래밍을 한다면, Akka와 같은 방식으로, 프레임워크를 사용하거나 만들어 쓰고 싶어졌다. (이미 있더라. CAF )

C++ 17 표준 라이브러리의 알고리즘 병렬화 소개

C++의 경우에도 지속적인 발전 방향이 병렬화/비동기를 상황에 따라 손쉽게 쓸 수 있으면서도 성능 향상을 노리는 방향인데, 이 방향에 Actor 모델이 적합하다는 결론에 도달했으니 Akka를 접하고 사용해보며 얻은게 많았다.

결국엔 로직 하나하나가 나쁜 퍼포먼스가 아니게끔 관리하는 것도 물론 중요하지만, 최대한 시스템 자원을 활용하는 것은 여러개의 작업이 병렬 진행되는 것도 중요하다.

이를 쉽게 해낼 수 있다는 점에서 혁신이 아닌가 싶다.

Java 적응기 02 - Netty

Java에서 가장 만족한 것이 무엇이냐고 물어본다면 나는 단연 Netty라고 말할 것이다. (그 다음은 Akka)

네트워크 라이브러리 작업을 많이 해본 나로썬, 같은 포지션의 Netty (같은 퀄리티라고 안했다)를 보면서 여러가지 감정이 들었다.

내가 네트워크 라이브러리 작업을 하며 고민한 것은 아래와 같다

  • 어디까지를 라이브러리의 역할로 두고, 어디까지가 사용자에게 맡길 것인가?
    • 프로젝트마다 특화된 기능을 어떻게 주입 받을 것인가?
      • 자체 암호화, 압축, 보안 등을 위한 패킷 구성
      • 패킷 슬라이스
        • 뭉쳐오는 패킷을 잘라주기
      • 패킷 이벤트를 구현 프로젝트에 어떻게 전달 할 지
      • 워커 스레드 처리 방식
      • 소켓 이벤트 스레드 (IOCP Worker thread 같은) 에서 워커 스레드로 전달하는 방식.
  • 위 기능들의 기본 값을 어떻게 제공해야 사용자에게 편리한 좋은 라이브러리가 되는 가?

특히나 나의 경우 여러 번 작업한 라이브러리에서, 이 부분에 대해 만족하지 못했다.

물론 Netty도 완벽하진 않지만 오랜 기간 많은 사용자들에게 사용되어오며, 적정선을 잘 찾은 느낌이다.

사용법도 아주 간단한 편에 속하며, 패킷 디코딩 문제를 여러가지 템플릿을 제공하며 특수화해서 처리 할 수도 있게끔 유연한 옵션을 제공했다.

나의 경우는 특화 or 기본 값만 생각했는데, Netty는 템플릿으로 여러가지 선택지를 미리 구현해두고 관리하고 있었다.

그리고 난 비동기 동작 요청 (주로 Send고, Connect, Disconnect 등)을, 별도의 핸들러를 통해서만 받았는데, 이에 대한 것도 Future로 처리 한 점도 훌륭했다. (나도 boost asio와 POSA2를 보고 변경하기 시작했지만 Netty의 비동기 패턴 적용 시점은 나보다 훨씬 빨랐다.)

굳이 프레임워크처럼 구현된 라이브러리와 비교하지 않더라도 C++에서 가장 범용적으로 쓰이는 네트워크 라이브러리인 boost asio에 비교했을 때 boost asio는 스레딩 제어를 비롯한 코어단 구현시 사용자의 선택에 따라 최적화 할 수 있게끔, 개발자가 직접 코딩하는 영광(?)을 안겨주고 학습 코스트도 함께 높였다.

즉 멀티 스레드에 대한 높은 이해와, boost asio API에 대한 높은 이해 (실제론 epoll이나 IOCP 개발을 해본 사람은 어느정도 이해할 수 있는 수준의 추상화긴 했다만은, 생각보다 처음 만져보는 사람들이 능수 능란하게 boost asio API를 사용하지 못한 경우를 많이 봤다.)를 필요로 하기에 궤를 달리한다.

내가 주로 사용하는 언어에 Netty와 같은 쉽게 사용할 수 있는 소켓 라이브러리가 존재한다는 것은 축복이며, Java진영이 Netty를 바탕으로 소켓 서버나 클라이언트가 필요한 수많은 라이브러리가 개발 코스트를 낮추어 많이 개발 될 수 있었다.

내가 내린 결론은 이런 부분마저 언어 철학의 차이가 아닌가 싶다.

C++은 선택지를 개발자에게 주어, 작은 부분까지 세심하게 결정하고 코스트를 다르게 가져갈 수 있게끔 하는 최적화에 큰 가치를 두는 문화이고, Java는 최적화의 여지가 줄어들 지언정 사용이 편하고 일정 수준 이상의 퍼포먼스를 내는 것에 큰 가치를 두는게 아닌가 싶다.

Netty를 사용한 경험이 내가 Java진영에서의 개발에 우호적인 생각을 갖게 된 첫 계기였다.

Java 적응기 01

사실 여러 번 밝힌대로, 나는 Java를 싫어했다.

내가 프로그래밍을 배우던 시기에 Java는 느려도 너무 느린 존재였다. 그렇다고 여타 스크립트 언어들 만큼 가볍게 쓰기에도 적합하지도 않았고.

내 뇌리에 박힌 어중간한 언어라는 인식이 꽤나 오랜 시간 Java를 선택하지 않게 했다.

이제와 고백하자면, C++ 부심도 상당했다.

C++의 학습 허들은 꽤나 높은편이다.

실제로 포인터 개념의 허들이 주를 이루는 C언어보다, C를 하위호환하며 C++로 구현하면서 생긴 복잡한 문제와 메모리를 직접 다루는 문제에 연관되어 사이드 이펙트로 이어질 수 있는 몇가지 구현 (가상 함수 테이블 이라던지, delete와 delete []의 차이 라던지, memcpy나 raw pointer를 다루다 생기는 커럽션 문제 라던지) 은 끔찍하다.

이런 문제는 많은 공부에도 경험 할 수 있는 재앙이며, 경험으로 인해 줄어들 뿐, 사라지지 않는다.

또한 수많은 레거시가 여전히 현역 코드로 사용되고 있음에서 발생하는 리스크 (매크로 함수 라던지, goto 지옥, n차 pointer의 향연, 모호한 메모리 제어권) 는 끔찍하다.

그럼에도 그렇게 어렵고 문제가 많은 언어를 집중해서 잘 썼을 때의 쾌감을 즐겼다. (혹자는 기술 변태라는 표현을 썼고, 나도 가끔씩 쓰게 됐다.)

나는 어려운 문제를 쉽게 푸는 것을 즐기는데, 그 방식 중 하나가 C++을 나의 제어권 하에 치밀한 계산 하에 안정성을 갖추는 일이었다.

그런 생각이 ruby on rails를 익히면서, 많이 변해갔다.

생산성이 좋은 언어를 접하고, 만들어진 것들을 활용 하는 것에 익숙해질 무렵, 나의 결론은 C#이었다.

Ruby나 python은 너무 느렸고, node.js는 철학이 부족했다.

node.js에 대해선 특히나 이견이 많이 있을거라고 생각하지만, 표준화가 많이 이뤄진 지금에서야 방향성과 아이덴티티가 생겼지, 3~4년 전만해도 adhoc 언어였다고 생각한다.

그럼 남는 것은 Java와 C#인데 이 중 C#은 unity3D를 쓰게되면서 익힌 것도 있지만, 언어 자체의 발전 속도나 완성도, MS가 관리하고 있는 정재된 사용 방식과, 일관성이 나에겐 큰 장점이었다.

유일한 단점이던 리눅스 환경 지원도, .NET CORE와 함께 해소되었다. (이전 글에서 언급했듯 아직 문제가 많은 .NET CORE의 부족한 라이브러리 풀과 이식률, 안정성에 대해서까지 옹호함은 아님을 밝힌다.)

(사심을 가득 담아) 머지 않아 C#이 더 인기를 얻게 될거라고 보지만, 아직은 그리고 국내는 더더욱 Java 천국임은 인정한다.

그러나 나는 그 것이 선점 효과라고만 생각했다.

다른 장점들을 크게 둘러보고 싶지 않아했음도 인정한다.

그렇기에 Java의 장점을 잘 알아보려하지 않았다.

그러던 차에 Java를 반쯤은 강요된 사용 기회를 갖게 됐고, 그래서 진지하게 Java를 사용하고 살펴보게 됐다.

그 결과 내가 얻은 결론은 다음과 같다.

  • Java의 과도기를 딛고 안정성과 최적화를 많이 이뤄낸 JVM 환경.
    • JVM 기반의 수 많은 언어들이 이를 증명.
  • Java의 안정적이고, 생산성이 뛰어난 수많은 라이브러리.
    • Netty
    • Akka
    • Spring
  • 다른 언어에 없는 것은 있어도, 다른 언어에 있는 것은 다 있다고 볼 수 있는 라이브러리 풀.
  • C++과 다르게 예외 처리에 강한 점.
    • 메모리 커럽션이 없어서 최악의 케이스가 덜 발생함.
  • 개발자 풀이 압도적으로 많은 점.

이런 장점들이 메인 언어로써 Java가 선택되게 된 계기 아닌가 싶다. 그 중에서도 나는 Netty와 Akka가 인상 깊었다.

위에 언급한 이런 장점에 비해 아쉬움도 많았다.

  • 생각보다 환경 설정에서 이슈가 많았는데, 이에 대한 원인 파악이 굉장히 어려운 편이었음.
    • 구글링해도 잘 안나옴.
    • 버전별로 다른 해결책이 필요한 경우가 많아 무의미해진 해결책을 시도해보느라 시간 소요가 되는 일이 비일 비재 했음.
  • 언어 발전 속도가 느려도 너무 느림.
    • 하위호환과 안정성 때문이란 얘기도 듣긴 했지만, 그걸 감안해도 너무 느리다.
    • 어설프게 지원된 Generic도 불만 요소.
  • Visual Studio 보다 아쉬운 개발 툴.
    • Eclipse는 물론이고, Intellij Idea도 Visual Studio 보단 많이 아쉽다.
  • 내가 경험한 다른 언어들보다 한두가지 아쉬움.
    • C#
      • LINQ
    • C++
      • multi_index

이런 몇가지 아쉬움이 있긴했으나, 그걸 감안하고도 학습 허들이 낮고 큰 어려움이 없이 비즈니스 로직에 집중 할 수 있었다. (이는 C#도 동일했다.)

무엇보다 가장 큰 아쉬움은 자바 개발 속도가 빠르지 못해, multi_index나 LINQ가 근 시일 내에는 추가되지 못할 것 같은 불안감이었다.

RxJava나, Akka를 보면 그렇지 않을 수 도 있을 것 같긴한데… 의지의 부족이 아닌가 싶은 생각도 든다.

적어도 내가 느낀 결론은 Java가 가장 널리 사용되고 있지만, 개선하거나 나아질 요소가 충분하다. 그에 비해 지나치게 느린 변화의 속도는 안정성을 위한 선택이라고만 느껴지진 않는다. 내 생각은 앞서 있는 진영의 여유? 그게 아니면 자만??

다 늘어놓고 보니, 이 글에서도 여전히 Java를 그리 선호하지 않는 냄새가 나는데, 실제로 그렇다.

그럼에도 불구하고 Java에서 느낀 여러가지 장점과 감상, 또 이미 다른 언어에 있지만 Java로 사용하게 되며 느끼게 되는 여러가지 장단점을 느꼈다.

음 아마도 앞으로 더 많이 사용하게 될 Java에 대해 익숙해져가는 과정에서의 감상과 경험담을 주제별로 다뤄보겠다.