[번역] 그루그 같은 뇌를 가진 개발자
이 글은 원저자 Carson Gross의 The Grug Brained Developer를 허락을 받아 번역한 글입니다.

자기 머리가 작다는 걸 아는 사람처럼 생각하기 위한 쉬운 안내서
들어가며
이 글은 그루그 같은 뇌를 가진 개발자가 소프트웨어 개발에 관해 모아 둔 생각입니다.
그루그는 그리 똑똑하지 않습니다. 그래도 오랫동안 프로그래밍을 하며 몇 가지는 배웠습니다. 아직도 대부분은 헷갈립니다.
그루그는 배운 것들을 짧고 쉽게 읽히는 재미있는 글로 모으려 합니다. 젊은 그루그인 여러분을 위해서이기도 하지만, 자기 자신을 위해서이기도 합니다. 나이가 들수록 아침에 뭘 먹었는지, 바지를 입기는 했는지 같은 중요한 일을 잊기 때문입니다.
머리가 큰 개발자는 많습니다. 그중에는 이 글이 마음에 안 들어 얼굴을 찌푸릴 사람도 있을 겁니다.
자기가 머리가 크다고 생각하는 개발자는 훨씬, 훨씬 많습니다. 이쪽은 분명 아마 어쩌면 더더욱 마음에 안 들어 할 겁니다. 찌푸린 얼굴이 많아집니다. 인터넷이란 원래 그렇습니다.
(참고로 그루그도 한때 자기가 머리가 큰 줄 알았습니다. 호되게 당하고 배웠습니다.)
괜찮습니다!
어쨌든 어느 정도는 자유로운 나라고, 결국 그렇게 중요한 일도 아닙니다. 그래도 재미있게 읽고, 그루그가 오랜 개발 인생에서 저지른 수많은 실수에서 뭔가 배우면 좋겠습니다.
영원한 적, 복잡성
그루그를 잡아먹는 최상위 포식자는 복잡성입니다.
복잡성은 나쁩니다.
다시 말합니다.
복잡성은 아주 나쁩니다.
이제 여러분이 말해 봅니다.
복잡성은 아주, 아주 나쁩니다.
복잡성과 싸울지 티라노사우루스와 일대일로 싸울지 고르라면, 그루그는 티라노사우루스를 고릅니다. 적어도 티라노사우루스는 눈에 보입니다.
복잡성은 악령입니다. 그루그 같은 뇌를 갖지 않은 개발자와 프로젝트 매니저를 통해 코드베이스에 들어옵니다. 이들은 의도는 좋지만 결국 몽둥이로 한 대 맞을 만합니다. 복잡성의 악령을 두려워하지 않고, 때로는 그런 악령이 있는지도 모릅니다.
어느 날까지는 코드베이스를 이해할 수 있고 일도 할 수 있습니다. 다 좋습니다!
그런데 다음 날은 아무것도 못 합니다. 코드에 복잡성의 악령이 들어왔습니다. 아주 위험한 상황입니다!
그루그는 복잡성의 악령을 볼 수는 없지만, 코드베이스 안에 있다는 건 느낍니다.
복잡성의 악령이 그루그를 놀립니다. 여기를 바꾸니 전혀 상관없는 저기가 망가집니다. 뭐라고요!?! 놀리고 또 놀립니다. 하하, 참 재미있습니다. 그루그는 프로그래밍이 정말 좋습니다. 선배 그루그가 권했던 반짝이는 돌 투기꾼이 되지 않아서 정말 좋습니다.
복잡성의 악령에게는 몽둥이가 통하지 않습니다. 악령을 들여보낸 개발자를 실제로 몽둥이로 때리는 것도 좋지 않습니다. 가끔은 그게 그루그 자신입니다!
슬프게도, 자주 그루그 자신입니다.
그래서 그루그는 다시, 또 자주 말합니다. 복잡성은 아주, 아주 나쁩니다.
아니요라고 말하기
복잡성의 악령에 맞서는 최고의 무기는 마법의 말, “아니요”입니다.
“아니요, 그루그는 그 기능 안 만듭니다.”
“아니요, 그루그는 그 추상화 안 만듭니다.”
“아니요, 그루그는 매일 몸에 물 안 묻힙니다. 검은 생각 주스도 덜 마시지 않습니다. 이제 그만 요구하십시오.”
주의할 점이 있습니다. 기술적으로는 좋은 조언이지만, 출세에는 나쁜 조언입니다. 반짝이는 돌을 더 많이 받고 커다란 개발자 부족을 이끌게 해 주는 마법의 말은 “네”입니다.
슬프지만 사실입니다. “네”라고 하는 법을 배우고, 실패하면 다른 그루그를 탓하는 법을 배웁니다. 출세를 위한 완벽한 조언입니다.
하지만 그루그는 자기 자신에게 솔직해야 합니다. “아니요”는 그루그의 마법의 말입니다. 처음에는 하기 어렵습니다. 특히 착하고, 남을 실망시키기 싫어하는 그루그라면 더 그렇습니다. 그런 그루그는 많습니다! 그래도 시간이 지나면 쉬워집니다. 반짝이는 돌더미가 조금 낮아질 수는 있습니다.
괜찮습니다. 어차피 그루그에게 반짝이는 돌이 얼마나 필요하겠습니까?
알겠다고 말하기
가끔은 타협해야 합니다. 안 그러면 반짝이는 돌을 못 받고, 그러면 공룡 고기도 못 먹습니다. 좋지 않습니다. 아내는 집에 있는 어린 그루그들에게 지붕도, 먹을 것도 필요하다고 단호하게 일깨워 줍니다. 복잡성의 악령에 관한 그루그의 쉰 번째 불평에는 관심이 없습니다.
이럴 때 그루그가 추천하는 말은 “알겠습니다”입니다.
“알겠습니다, 그루그가 그 기능 만듭니다.”
그런 다음 시간을 들여 문제의 80/20 해법을 생각하고, 그걸 만듭니다. 80/20 해법은 “코드 20으로 원하는 것 80을 얻는” 해법입니다. 프로젝트 매니저가 원하는 온갖 기능을 다 갖추지는 못할 수 있습니다. 조금 못생겼을 수도 있습니다. 그래도 작동하고, 대부분의 가치를 전달하며, 복잡성의 악령도 대체로 어느 정도 막아 줍니다.
가끔은 프로젝트 매니저에게 말하지 않고 그냥 80/20 방식으로 하는 편이 나을 수도 있습니다. 허락보다 용서받기가 쉽습니다. 프로젝트 매니저는 일이 너무 많고 상대할 그루그도 많아, 마음이 나비처럼 이리저리 날아다닐 때가 있습니다. 기능이 원래 뭘 해야 했는지 잊기도 하고, 다른 일로 넘어가거나, 퇴사하거나, 해고되기도 합니다. 그루그는 많이 봤습니다.
어차피 프로젝트 매니저에게도 이로운 일이니, 그루그는 보통 크게 죄책감을 느끼지 않습니다.
코드 나누기
다음 전략은 훨씬 어렵습니다. 코드베이스를 잘 나누는 일입니다. 멋진 말로는 “코드를 적절히 분해하기(factoring)”입니다. 시스템마다 너무 달라서 일반적인 조언을 하기는 어렵습니다. 그래도 그루그가 믿게 된 한 가지는 있습니다. 애플리케이션을 너무 일찍 나누지 않습니다!
프로젝트 초반에는 모든 게 추상적이고 물 같습니다. 애쓰는 그루그의 뇌가 붙잡을 만한 단단한 것이 거의 없습니다. 시스템의 “모양”이 잡히고, 대체 뭘 하고 있는지 알기까지 시간이 걸립니다. 그루그는 초반에는 코드를 나누지 않으려 합니다. 그러다 보면 어느 순간 코드베이스에서 나누기 좋은 지점이 보입니다.
나누기 좋은 지점은 시스템의 나머지 부분과 맞닿는 인터페이스가 좁습니다. 적은 수의 함수나 추상화가 복잡성의 악령을 안에 감춥니다. 수정에 가둬 놓은 것 같습니다.
복잡성의 악령을 수정 안에 제대로 가두면 그루그는 꽤 만족합니다. 숙적을 가두는 기분은 최고입니다!
그루그는 코드에서 나눌 지점이 드러날 때까지 참을성 있게 지켜보며 천천히 리팩터링합니다. 시간이 흐르고 경험이 쌓이면 코드베이스도 모양을 갖춥니다. 딱 떨어지는 규칙은 없습니다. 그루그는 나눌 지점을 보면 알아봅니다. 그걸 알아보는 눈을 기르는 데 시간이 걸릴 뿐입니다. 인내심이 필요합니다.
가끔은 너무 일찍 나눴다가 추상화를 잘못 잡습니다. 그래서 그루그는 기다리는 쪽을 선호합니다.
머리가 큰 개발자는 이런 방식을 아주 싫어할 때가 많습니다. 프로젝트가 시작되자마자 온갖 추상화를 만들어 냅니다.
그루그는 몽둥이를 집어 들고 외치고 싶어집니다. “큰 머리는 코드 유지보수 안 합니다! 큰 머리는 다음 아키텍처 위원회로 가 버리고, 코드는 그루그한테 떠넘깁니다!”
하지만 그루그는 감정을 다스리는 법을 배웠습니다. 그루그와 동물의 중요한 차이입니다.
대신 프로젝트 초반에는 머리가 큰 개발자에게 UML 다이어그램 같은 일을 맡겨 피해를 줄이려 합니다. 코드에는 해가 없고, 어차피 버릴 가능성도 큽니다. 아니면 내일까지 작동하는 데모를 요구합니다.
작동하는 데모는 특히 좋은 방법입니다. 큰 머리가 실제로 돌아가는 무언가를 만들게 합니다. 이야기할 대상도 생기고, 실제로 일을 하는 코드도 볼 수 있습니다. 큰 머리가 현실을 더 빨리 이해하는 데 도움이 됩니다.
기억합니다! 큰 머리는 머리가 큽니다! 그 능력을 좋은 데 쓰게 하면 됩니다. 실수로 복잡성의 악령을 섬기게 두지 않으면 됩니다. 그루그는 그런 일을 많이 봤습니다.
(최고의 그루그는 여러 큰 머리를 올바른 방향으로 이끌어 복잡성의 악령을 가두는 수정을 많이 만들어 냅니다. 그런 그루그에게는 커다란 반짝이는 돌더미가 기다립니다!)
데모를 만드는 이 방식을 가끔 “프로토타입”이라고 부르기도 합니다. 프로젝트 매니저에게 더 멋지게 들립니다.
그루그는 소프트웨어를 만들 때 일찍 프로토타입을 만들라고 합니다. 큰 머리가 많다면 특히 그렇습니다.
테스트
그루그는 테스트를 사랑하면서도 미워합니다. 테스트는 셀 수 없이 많이 그루그를 구해 줬습니다. 그루그는 테스트를 사랑하고 존중합니다.
안타깝게도 테스트 주술사도 많습니다. 어떤 주술사는 테스트를 우상으로 섬깁니다. 그루그가 코드를 쓰기도 전에, 다루는 분야가 뭔지 알기도 전에 “테스트부터” 같은 걸 요구합니다!
그루그가 다루는 분야도 모르는데 대체 뭘 테스트합니까!?
“걱정 마세요. 테스트가 뭘 해야 할지 알려 줄 거예요.”
그루그는 또 슬그머니 몽둥이로 가는 손을 발견합니다. 그래도 침착함을 유지합니다.
그루그는 프로토타입 단계를 지나 코드가 자리를 잡기 시작한 뒤에 대부분의 테스트를 작성하는 편을 좋아합니다.
하지만 여기서는 정말 철저해야 합니다!
“그루그 컴퓨터에서는 되는데!” 하면서 테스트를 안 쓰고 넘어가기 쉽습니다.
아주, 아주 나쁩니다. 다른 컴퓨터에서도 된다는 보장은 없습니다. 앞으로도 그루그 컴퓨터에서 잘된다는 보장도 없습니다. 그런 일은 많습니다.
테스트가 중요하다는 주술사의 말은 맞습니다. 평생 쓸 만한 기능 하나 완성하지 않고 테스트 이야기만 하는 주술사도 종종 있습니다. 몽둥이로 맞을 만하지만, 뜻은 좋습니다.
주술사들은 단위 테스트 이야기도 많이 합니다. 하지만 그루그에게는 그렇게 유용하지 않았습니다. 경험상 이상적인 테스트는 단위 테스트도, 엔드투엔드 테스트도 아닙니다. 그 중간의 테스트입니다.
단위 테스트는 괜찮습니다. 하지만 구현이 바뀌면 깨집니다. 구현은 API보다 훨씬 자주 바뀝니다! 리팩터링도 어려워집니다. 솔직히 버그는 다른 코드와 맞물리면서 생기는 경우도 많습니다. 코드가 바뀌면 테스트를 버릴 때도 많습니다.
그루그는 주로 프로젝트 초반에 단위 테스트를 씁니다. 일을 시작하는 데 도움이 되지만, 너무 애착을 갖거나 오래도록 가치가 남으리라 기대하지는 않습니다.
엔드투엔드 테스트는 좋습니다. 시스템 전체가 작동한다는 걸 보여 줍니다. 하지만! 깨졌을 때 이유를 알기 어렵고, 그루그를 아주 자주 미치게 합니다. 그러다 “아, 저거 맨날 깨져” 하며 무시하게 되는 그루그도 있습니다. 아주 나쁩니다!
그 중간의 테스트를 주술사들은 “통합 테스트”라고 부릅니다. 종종 얼굴을 찌푸리면서 말입니다. 하지만 그루그에게는 통합 테스트가 딱 좋습니다. 시스템이 올바른지 확인할 만큼 수준이 높으면서, 좋은 디버거만 있으면 어디가 고장 났는지 쉽게 알 수 있을 만큼 수준이 낮습니다.
그루그는 특히 초반에 단위 테스트를 조금 쓰는 편을 좋아합니다. 하지만 코드 전체를 100% 테스트하지는 않습니다. “테스트부터”는 더더욱 아닙니다. “만들면서 테스트하기”가 그루그에게는 꽤 잘 맞습니다. 특히 이것저것 알아가는 중에는 그렇습니다.
나눌 지점이 드러나고 시스템이 안정되면, 그루그는 통합 테스트에 무섭게 집중합니다! 잘 나눈 경계의 API는 구현보다 안정적일 겁니다. 그러면 통합 테스트는 오래도록 가치가 남고 디버깅도 쉽습니다.
잘 추려 낸 작은 엔드투엔드 테스트 스위트도 만듭니다. 계속 작동하도록 철저히 관리합니다. 안 그러면 몽둥이로 맞습니다. 가장 많이 쓰는 UI 기능과 특히 중요한 엣지 케이스 몇 가지에 집중합니다. 너무 많으면 유지보수가 불가능해지고 결국 무시하게 됩니다.
그루그에게는 이게 이상적인 테스트 구성입니다.
마음에 안 들 수도 있지만, 이것이 그루그 테스트의 정점입니다.
또 그루그는 테스트에서 모킹(mocking)을 좋아하지 않습니다. 꼭 필요할 때만 씁니다. 그런 때는 드물거나 아예 없습니다. 쓰더라도 경계나 시스템 단위로 크게 묶어서만 모킹합니다.
그루그가 싫어하는 “테스트부터”에도 예외는 하나 있습니다. 버그를 발견했을 때입니다. 그루그는 늘 회귀 테스트로 버그부터 재현하고, 그다음에 고치려 합니다. 이상하게 이 경우만큼은 그 편이 더 잘됩니다.
애자일
그루그는 애자일이 끔찍하지도, 좋지도 않다고 생각합니다.
어쨌든 개발을 진행하는 최악의 방법은 아닙니다. 다른 방법보다 나을 수도 있으니, 괜찮다고 생각합니다.
하지만 위험한 건 애자일 주술사입니다! 애자일 주술사에게 반짝이는 돌을 아주 많이 빼앗깁니다!
애자일 프로젝트가 실패할 때마다 주술사는 말합니다. “애자일을 제대로 안 해서 그래요!” 주술사에게 참 편리한 말입니다. 어린 그루그들에게 애자일을 더 잘 가르쳐 주겠다며 반짝이는 돌을 더 요구합니다. 위험합니다!
애자일 이야기가 너무 많아지면 그루그는 몽둥이를 집어 들고 싶어집니다. 그래도 늘 침착함을 유지합니다.
소프트웨어 성공에는 프로토타입, 도구, 좋은 그루그 채용이 더 중요합니다. 애자일 절차도 괜찮고 어느 정도 도움이 되지만, 너무 진지하게 받아들이면 해가 되기도 합니다.
그루그는 애자일 주술사가 뭐라고 하든 모든 소프트웨어 문제를 해결해 줄 은 몽둥이는 없다고 말합니다. 위험합니다!
리팩터링
리팩터링은 괜찮은 일이고, 좋은 선택일 때도 많습니다. 특히 프로젝트 후반에 코드가 자리를 잡았을 때 그렇습니다.
하지만 그루그는 개발하면서 “리팩터링”이 완전히 엉뚱한 길로 빠져, 득보다 실이 커지는 일을 많이 봤습니다.
어떤 리팩터링은 잘되고 어떤 리팩터링은 실패하는 이유를 정확히 알지는 못합니다. 그래도 규모가 클수록 실패할 가능성이 커 보였습니다.
그래서 그루그는 리팩터링을 비교적 작게 유지하고, 진행하는 동안 “물가에서 너무 멀리 나가지” 않으려 합니다. 이상적으로는 시스템이 내내 작동하고, 한 단계를 마친 다음에 다음 단계를 시작합니다.
이럴 때 엔드투엔드 테스트는 생명의 은인입니다. 다만 왜 깨졌는지 알기가 아주 어려울 때도 많습니다. 리팩터링 인생이란 그렇습니다.
추상화를 너무 많이 도입하면 리팩터링도, 시스템도 실패하기 쉽습니다. J2EE를 도입하던 때가 좋은 예입니다. 큰 머리들이 모여 앉아 추상화를 너무 많이 생각했습니다. 좋은 결과는 없었고, 많은 프로젝트가 피해를 봤습니다.
그루그가 다니던 회사에서 코드베이스의 복잡성의 악령을 관리하고 가두려고 OSGi를 도입한 일도 좋은 예입니다. OSGi는 도움이 안 됐을 뿐 아니라 악령을 훨씬 강하게 만들었습니다! 게다가 코드를 다시 짜느라 최고의 개발자들이 몇 년 치 공수까지 들였습니다! 악령은 더 강해지고, 이제 기능도 구현할 수 없습니다! 아주 나쁩니다!
체스터턴의 울타리
현명한 그루그 주술사 체스터턴은 이렇게 말했습니다.
어떤 제도나 법이 있다고 합시다. 간단히 말해 길을 가로막은 울타리나 문이라고 해 봅시다. 현대적인 개혁가는 경쾌하게 다가가 “이게 무슨 쓸모가 있는지 모르겠군. 없애 버립시다”라고 말합니다. 그러면 더 현명한 개혁가는 이렇게 답하는 편이 좋습니다. “쓸모를 모르겠다면, 없애도록 내버려 둘 수는 없습니다. 돌아가서 생각해 보세요. 다시 와서 그 쓸모를 알겠다고 말할 수 있게 되면, 그때는 없애도 좋다고 할 수 있겠습니다.”
나이 든 그루그는 이 교훈을 잘 배운 경우가 많습니다. 코드가 아무리 못생겨 보여도 함부로 뜯어내지 않습니다.
그루그는 모든 프로그래머에게 어느 정도 플라톤주의자 기질이 있음을 압니다. 코드에서도 천체의 음악 같은 완벽함을 바랍니다. 하지만 여기에 위험이 있습니다. 세상은 못생기고 엉망인 경우가 많습니다. 코드도 그럴 수밖에 없습니다.
머리가 큰 사람이나 자기가 머리가 크다고 생각하는 사람은 겸손하기 어렵습니다. 그루그도 마찬가지입니다. 하지만 “아, 이거 마음에 안 듭니다. 그루그가 고칩니다” 하고 나섰다가 몇 시간씩 고생하고도 나아지는 게 없거나, 오히려 시스템이 더 나빠지는 일을 자주 겪습니다.
개발을 시작한 무렵 그루그는 몽둥이를 마구 휘두르며 코드베이스에 뛰어들어 모조리 때려 부수곤 했습니다. 좋지 않다는 걸 배웠습니다.
시스템을 절대 개선하지 말라는 말은 아닙니다. 그건 참 어리석은 말입니다. 다만 시간을 들여 시스템부터 이해하길 권합니다. 시스템이 클수록 더 그렇습니다. 완벽하지 않더라도 오늘 잘 돌아가는 코드는 존중합니다.
이럴 때 테스트는 울타리를 왜 부수면 안 되는지 알려 주는 좋은 단서가 됩니다!
마이크로서비스
그루그는 큰 머리들이 왜 시스템을 제대로 나누는 가장 어려운 문제에 네트워크 호출까지 더하는지 궁금합니다.
그루그에게는 아주 혼란스럽습니다.
도구
그루그는 도구를 좋아합니다. 도구와 감정 조절이 그루그와 공룡을 구분합니다! 도구는 그루그 대신 생각해 줍니다. 덕분에 그루그의 뇌만으로는 만들 수 없는 코드도 만듭니다. 언제나 마음이 놓입니다! 그루그는 새 환경에 가면 생산성을 높이려고 주변 도구를 익히는 데 시간을 씁니다. 도구를 2주 동안 익히면 개발 속도가 두 배가 되기도 합니다. 문서가 없어 직접 뒤지고 다른 개발자에게 도움을 청해야 할 때도 많습니다.
IDE의 코드 자동 완성 덕분에 모든 API를 외울 필요가 없습니다. 아주 중요합니다!
그루그는 자동 완성 없이 자바로 프로그래밍하는 건 거의 불가능합니다!
가끔은 정말 생각하게 됩니다.
좋은 디버거는 그 무게만큼의 반짝이는 돌과 맞먹는 가치가 있습니다. 사실 그 이상입니다. 버그를 만나면 그루그는 가진 돌을 전부 내주고, 어쩌면 아이 몇 명까지 내주고서라도 좋은 디버거를 얻고 싶을 때가 많습니다. 어차피 그루그가 알기로 디버거는 무게도 없습니다.
그루그는 새 프로그래머에게 쓸 수 있는 디버거를 깊이 익히라고 늘 권합니다. 조건부 중단점, 표현식 평가, 스택 탐색 같은 기능은 대학 수업보다 컴퓨터에 대해 더 많이 가르쳐 줄 때도 많습니다!
그루그는 도구 개선을 멈추지 말라고 합니다.
타입 시스템
그루그는 프로그래밍을 쉽게 해 주는 타입 시스템을 아주 좋아합니다. 키보드에서 점을 눌렀을 때, 할 수 있는 일의 목록이 마법처럼 뜨는 순간에 가장 큰 가치를 느낍니다. 그루그에게는 이게 타입 시스템 가치의 90% 이상입니다.
머리가 큰 타입 시스템 주술사는 타입의 올바름이 타입 시스템의 핵심이라고 자주 말합니다. 그런데 그런 주술사 중에는 코드를 잘 내놓지 않는 사람도 있습니다. 한 번도 배포하지 않은 코드는 어떤 의미에서는 올바를 수 있습니다. 하지만 그루그가 말하는 올바름은 그런 뜻이 아닙니다.
그루그에게 타입 시스템의 가장 큰 장점은 도구가 할 수 있는 일을 마법처럼 보여 주고 코드를 완성해 주는 것입니다. 올바름도 좋지만, 그만큼은 아닙니다.
여기서도 큰 머리를 조심합니다!
어떤 큰 머리는 타입 시스템으로 생각하고 보조정리(lemma)로 말합니다. 위험할 수 있습니다!
추상화 수준이 너무 높아질 위험이 있습니다. 큰 머리가 쓴 타입 시스템 코드는 플라톤적이고 일반적인 튜링 계산 모델을 코드베이스에 유체 이탈시켜 놓은 것처럼 됩니다. 그루그는 혼란스럽습니다. 어느 정도 우아하다는 데는 동의합니다. 하지만 정작 해야 할 일인 그루그 주식회사의 몽둥이 재고 수량 기록 같은 일은 아주 어려워집니다.
여기서는 제네릭(generics)이 특히 위험합니다. 그루그는 제네릭을 주로 컨테이너 클래스에만 쓰려 합니다. 거기서 가장 큰 가치를 얻기 때문입니다.
제네릭의 엄청난 유혹은 함정입니다! 복잡성의 악령이 아주 좋아하는 수법입니다! 조심합니다!
타입 시스템의 가장 큰 가치는 언제나 여기서 나옵니다. 점을 누르면 그루그가 할 수 있는 일이 보입니다. 절대 잊지 않습니다!
표현식의 복잡성
그루그도 한때는 코드 줄 수를 최대한 줄이려고 했습니다. 이런 코드를 썼습니다.
if(contact && !contact.isActive() && (contact.inGroup(FAMILY) || contact.inGroup(FRIENDS))) {
// ...
}
시간이 지나니 이런 코드는 디버깅하기 어렵다는 걸 배웠습니다. 이제는 이렇게 쓰는 편을 좋아합니다.
if(contact) {
var contactIsInactive = !contact.isActive();
var contactIsFamilyOrFriends = contact.inGroup(FAMILY) || contact.inGroup(FRIENDS);
if(contactIsInactive && contactIsFamilyOrFriends) {
// ...
}
}
젊은 그루그들은 늘어난 줄 수와 쓸데없는 변수에 질겁하며 비명을 지릅니다. 그루그는 몽둥이로 자신을 지킬 준비를 합니다.
다른 개발자들이 달려들며 몽둥이 싸움이 시작됩니다. 그루그는 외칩니다. “디버깅하기 쉽습니다! 표현식마다 결과가 더 잘 보이고, 이름도 좋습니다! 조건식을 이해하기 쉽습니다! 디버깅하기 쉽습니다!”
확실히 디버깅하기 쉽습니다. 몽둥이 싸움이 끝나고 젊은 그루그들이 진정한 뒤 잠깐 생각해 보면, 그루그가 맞다는 걸 깨닫습니다.
그루그도 아직 첫 번째 예시 같은 코드를 쓰다가 후회할 때가 많습니다. 그래서 젊은 그루그를 탓하지 않습니다.
DRY
DRY는 “반복하지 말라(Don't Repeat Yourself)”는 뜻입니다. 대부분의 개발자에게 강한 영향력을 가진 격언입니다.
그루그는 DRY를 존중하고 좋은 조언이라고 생각합니다. 하지만 모든 일에는 균형을 권합니다. 큰 머리 중에서도 가장 그루그다운 아리스토텔레스가 권했듯이 말입니다.
레아 베루(Lea Verou)의 재미있는 그래프는 반복을 피하려는 그루그의 열정과도 맞아떨어집니다.

프로그래밍을 한 지 10년이 지나자 그루그는 코드 반복에 예전만큼 신경 쓰지 않게 됐습니다. 반복되는 코드가 충분히 단순하고 명확하다면 괜찮습니다. 조금씩 바꿔 가며 코드를 반복하거나 복사해서 붙여 넣는 편이, 콜백과 클로저를 잔뜩 인자로 넘기거나 정교한 객체 모델을 만드는 것보다 낫다는 생각이 듭니다. 얻는 것은 너무 적은데, 너무 어렵고 복잡해질 때가 있습니다.
여기서 균형을 잡기는 어렵습니다. 반복되는 코드를 보면 그루그는 여전히 자주 빤히 쳐다보며 “음” 합니다. 그래도 경험상 코드 반복이 복잡한 DRY 해법보다 나을 때가 있습니다.
주의합니다! 뭐든 글자 그대로 받아들이는 개발자라면 그래프의 “작동하는가” 선을 너무 진지하게 보지 않길 바랍니다. 농담입니다.
관심사 분리(SoC)
관심사 분리(Separation of Concerns, SoC)도 많은 개발자의 마음을 사로잡은 개념입니다. 시스템의 서로 다른 측면을 별도의 코드 영역으로 나누자는 생각입니다.
웹 개발의 대표적인 예는 스타일(CSS 파일), 마크업(HTML 파일), 로직(자바스크립트 파일)을 나누는 것입니다.
여기서는 그루그의 얼굴이 DRY 때보다 훨씬 찌푸려집니다. 실제로 관심사 분리에 맞서 동작의 지역성(locality of behavior, LoB)이라는 대안 설계 원칙을 다룬 큰 머리스러운 글도 썼습니다.
그루그는 어떤 일을 하는 대상에 그 일을 하는 코드를 붙여 두는 편을 훨씬 좋아합니다. 그러면 그 대상을 볼 때 무슨 일을 하는지 알 수 있습니다. 언제나 마음이 놓입니다!
관심사를 나누면 버튼이 어떻게 작동하는지 이해하려고 온갖 파일을 이리저리 뒤져야 할 때가 많습니다. 아주 헷갈리고 시간도 낭비합니다. 나쁩니다!
클로저
그루그는 알맞은 일에 쓰는 클로저를 좋아합니다. 보통은 객체 컬렉션을 대상으로 하는 연산을 추상화하는 일입니다.
그루그는 클로저가 소금, 타입 시스템, 제네릭과 같다고 경고합니다. 조금만 써도 큰 효과가 있지만, 너무 많이 쓰면 망치기 쉽고 심장마비를 일으킵니다.
자바스크립트 개발자는 자바스크립트의 아주 특별한 복잡성의 악령을 “콜백 지옥”이라고 부릅니다. 자바스크립트 라이브러리에서 클로저를 너무 많이 쓴 탓입니다. 참 슬픕니다. 하지만 솔직히 말하면 자바스크립트 개발자가 자초한 일입니다.
로깅
그루그는 로깅을 아주 좋아하고 많이 하길 권합니다. 특히 클라우드에 배포한다면 그렇습니다. 그루그가 아닌 어떤 사람들은 로깅이 비싸고 중요하지 않다고 합니다. 그루그도 예전에는 그렇게 생각했습니다. 이제는 아닙니다.
재미있는 이야기가 있습니다. 그루그는 우상인 롭 파이크가 구글에서 로깅을 맡고 있다는 걸 알고 생각했습니다. “롭 파이크가 로깅을 한다면, 그루그는 거기서 대체 뭘 합니까?!?” 그래서 구글에 가려는 생각을 접었습니다. 알고 보니 구글에게 로깅은 아주 중요했습니다. 그러니 최고의 프로그래머가 맡는 게 당연합니다, 그루그!
그루그, 그렇게 그루그 같은 생각 좀 그만합니다. 덕분에 반짝이는 돌이 훨씬 적습니다!
뭐, 어쨌든 좋은 회사에 갔고 롭 파이크의 옷차림도 점점 종잡을 수 없어졌으니 결국 잘 풀렸습니다. 그래도 요점은 같습니다. 로깅은 아주 중요합니다!
그루그의 로깅 조언은 이렇습니다.
- 코드의 주요 논리 분기(if/for)를 모두 기록합니다.
- 클라우드 인프라에서 “요청”이 여러 컴퓨터를 거친다면, 로그를 묶어 볼 수 있게 모든 로그에 요청 ID를 넣습니다.
- 가능하면 로그 수준을 동적으로 조절하게 만듭니다. 그루그가 문제를 디버깅할 때 켜고 끌 수 있도록 합니다. 문제는 많습니다!
- 가능하면 사용자별로 로그 수준을 설정해, 특정 사용자의 문제를 디버깅할 수 있게 합니다.
마지막 두 가지는 운영 중인 시스템의 버그와 싸울 때 특히 유용한 몽둥이가 됩니다.
안타깝게도 로깅 라이브러리는 아주 복잡할 때가 많습니다. 자바, 왜 이럽니까? 그래도 로깅 인프라를 “딱 맞게” 갖추는 데 시간을 들일 가치는 있습니다. 그루그의 경험상 나중에 크게 보답받습니다.
그루그는 학교에서 로깅을 더 많이 가르치면 좋겠다고 생각합니다.
동시성
그루그는 제정신인 모든 개발자와 마찬가지로 동시성을 두려워합니다.
가능하면 단순한 동시성 모델에 의존하려 합니다. 상태를 저장하지 않는 웹 요청 핸들러나, 작업끼리 의존하지 않고 API도 단순한 원격 작업자를 위한 큐 같은 것입니다.
웹에서는 낙관적 동시성(optimistic concurrency)이 잘 맞는 것 같습니다.
가끔은 스레드 지역 변수(thread local variable)를 꺼내 씁니다. 보통 프레임워크 코드를 작성할 때입니다.
자바의 ConcurrentHashMap처럼 좋은 동시성 자료 구조를 제공하는 언어도 있습니다. 그래도 제대로 쓰려면 그루그가 조심해야 합니다.
그루그는 얼랭(Erlang)을 써 본 적은 없습니다. 좋은 이야기는 들었습니다. 하지만 그루그 눈에는 언어가 이상하게 생겼습니다. 미안합니다.
최적화
엄청나게 큰 머리 중에서도 가장 큰 머리를 가진 개발자가 말했습니다.
섣부른 최적화는 모든 악의 근원입니다.
대부분 아는 말입니다. 그루그도 가장 큰 머리의 말에 겸손하면서도 격렬하게 동의합니다.
그루그는 최적화를 시작하기 전에, 구체적인 성능 문제를 보여 주는 실제 환경의 성능 프로파일부터 확보하길 늘 권합니다.
진짜 문제가 뭔지는 알 수 없습니다. 그루그는 자주 놀랍니다! 아주 자주!
CPU에만 집중하지 않도록 조심합니다. CPU는 눈에 잘 들어오고, 학교에서도 빅오 표기법을 많이 배웁니다. 하지만 느려지는 근본 원인이 CPU가 아닐 때도 많습니다. 그루그를 포함해 많은 사람이 놀랍니다.
네트워크 호출은 수백만, 수천만 번의 CPU 사이클과 맞먹습니다. 가능하면 언제나 최소화합니다. 머리가 큰 마이크로서비스 개발자는 잘 듣습니다!
경험이 부족한 큰 머리는 중첩 반복문을 보고 자주 말합니다. “O(n^2)? 내 눈앞에서는 안 됩니다!”
복잡성의 악령이 미소 짓습니다.
API
그루그는 좋은 API를 좋아합니다. 좋은 API는 그루그를 너무 많이 생각하게 하지 않습니다.
안타깝게도 많은 API는 아주 나쁩니다. 그루그를 꽤 많이 생각하게 합니다. 이유는 많지만, 두 가지만 들면 이렇습니다.
- API를 만드는 사람이 API의 사용 방식보다 구현이나 API가 다루는 분야를 중심으로 생각합니다.
- API를 만드는 사람이 너무 추상적이고 큰 머리스럽게 생각합니다.
보통 그루그는 API의 세부 사항에 깊은 관심이 없습니다. 파일을 쓰거나 목록을 정렬하거나, 뭐든 그 일을 하고 싶을 뿐입니다. 그냥 write()나 sort() 같은 걸 호출하고 싶습니다.
그런데 머리가 큰 API 개발자가 말합니다.
“잠깐, 그루그! 그 파일은 쓰기 모드로 열었습니까? 정렬에 쓸 Comparator는 정의했습니까?”
그루그는 또 몽둥이로 가는 손을 붙잡습니다.
지금 그런 건 관심 없습니다. 그냥 정렬하고 파일에 쓰고 싶습니다, 큰 머리 선생님!
그루그도 머리가 큰 API 설계자의 말에 일리가 있고, 가끔은 그런 게 중요하다는 걸 압니다. 하지만 그렇지 않을 때가 많습니다. 간단한 일은 간단한 API로 하고, 복잡한 일도 더 복잡한 API로 할 수 있게 설계하면 좋겠습니다.
그루그는 이를 API에 “계층 두기”라고 부릅니다. 다양한 그루그의 필요에 맞춰 복잡도가 다른 API를 두세 개 두는 것입니다.
객체 지향이라면 API를 딴 데 두지 말고 그 대상에 둡니다. 자바가 이걸 가장 못합니다!
그루그는 자바에서 리스트를 필터링하고 싶습니다.
“스트림으로 변환했습니까?”
알겠습니다. 그루그가 스트림으로 바꿉니다.
“좋습니다. 이제 필터링할 수 있습니다.”
좋습니다. 그런데 반환해야 하는 건 리스트입니다! 지금은 스트림입니다!
“그럼 스트림을 리스트로 수집했습니까?”
뭐라고요?
“Collector<? super T, A, R>를 정의해서 스트림을 리스트로 수집합니다.”
그루그는 조상의 무덤에 맹세코 이 방의 모든 사람을 몽둥이로 때리고 싶습니다. 하지만 대신 둘까지 세고 침착함을 유지합니다.
filter()처럼 흔한 기능은 리스트에 두고 리스트를 반환하게 만듭니다. 머리가 큰 자바 API 개발자는 잘 듣습니다!
아무도 “스트림”에 관심 없습니다. 들어 본 적도 없습니다. 네트워킹 API도 아니지 않습니까. 자바 그루그는 다 리스트를 씁니다, 큰 머리 선생님!
파싱
그루그는 틈만 나면 프로그래밍 언어 만들기를 좋아합니다. 파서를 만드는 가장 재미있고 아름다운 방법은 재귀 하강(recursive descent)이라고 말합니다.
안타깝게도 큰 머리들의 학교에서는 파서 생성 도구만 가르치는 경우가 많습니다. 도구를 좋아하는 그루그도 여기서는 아닙니다. 파서 생성 도구가 만드는 코드는 끔찍한 뱀 둥지 같습니다. 이해할 수 없습니다. 상향식이라니, 뭐라고요? 문법의 재귀적인 성질은 그루그에게 감추고, 디버깅은 불가능하게 만듭니다. 그루그 생각에는 아주 나쁩니다!
그루그는 그 이유가 이렇다고 생각합니다. 복잡성의 악령은 코드베이스와 이해에는 나쁘지만, 학술 논문을 많이 만드는 데는 아주 좋습니다. 슬프지만 사실입니다.
학교에서는 외면해도 실제 운영에 쓰는 파서는 거의 언제나 재귀 하강입니다! 그루그는 파싱이 얼마나 단순한지 알고 화가 났습니다! 파싱은 큰 머리만 쓰는 마법이 아닙니다. 여러분도 할 수 있습니다!
머리가 큰 개발자 밥 나이스트롬(Bob Nystrom)이 큰 머리 부족의 명예를 회복해 줘서 그루그는 아주 기뻤습니다. 재귀 하강을 다룬 훌륭한 책, Crafting Interpreters를 썼습니다.
책은 온라인에서 무료로 볼 수 있습니다. 그래도 관심 있는 그루그라면 책을 사길 강력히 권합니다. 그런 책은 사 주는 게 좋습니다. 큰 머리의 조언이 많이 담겨 있습니다. 그루그는 이 책을 아주 좋아합니다. 방문자 패턴(visitor pattern)만 빼고 말입니다. 함정입니다!
방문자 패턴
프런트엔드 개발
그루그가 아닌 어떤 사람들은 웹 개발을 하게 되면 말합니다.
“좋아, 프런트엔드와 백엔드 코드베이스를 나누고, 요즘 뜨는 새 SPA 라이브러리를 쓰자. HTTP로 백엔드의 GraphQL JSON API와 통신하면 되겠네. 하이퍼텍스트를 보내지도 않는데 HTTP라니 재미있군.”
이제 복잡성의 악령 소굴이 두 개입니다.
더 나쁜 건 프런트엔드의 악령이 훨씬 강하다는 점입니다. 그루그가 보기에는 프런트엔드 업계 전체의 영혼을 깊이 사로잡고 있습니다.
백엔드 개발자는 단순하게 유지하려고 하고, 그럭저럭 해내기도 합니다. 그런데 프런트엔드 개발자는 아주 빠르게 복잡하게 만들고 코드를 잔뜩 들여옵니다. 복잡성의 악령입니다.
그저 폼을 데이터베이스에 넣는 웹사이트거나 단순한 소개 사이트여도 그렇습니다!
이제 다들 이렇게 합니다!
그루그는 이유를 잘 모릅니다. 아마 페이스북과 구글이 그러라고 해서인 것 같습니다. 하지만 그루그에게는 썩 좋은 이유로 들리지 않습니다.
그루그는 모두가 쓰는 크고 복잡한 프런트엔드 라이브러리를 좋아하지 않습니다.
그래서 피하려고 htmx와 hyperscript를 만들었습니다.
복잡성은 낮게, HTML은 단순하게 유지합니다. 복잡성의 악령이 살기 좋은 자바스크립트는 잔뜩 쓰지 않습니다.
여러분에게도 잘 맞을 수 있습니다. 다만 채용 공고는 없습니다. 미안합니다.
취업에는 리액트가 낫고, 특정 유형의 애플리케이션에도 더 잘 맞습니다. 하지만 원하든 원하지 않든 복잡성의 악령을 섬기는 신도가 됩니다. 미안합니다. 프런트엔드 인생이란 그렇습니다.
유행
개발에는 유행이 많습니다. 특히 요즘 프런트엔드 개발이 그렇습니다.
백엔드는 더 낫고 더 지루합니다. 나쁜 아이디어를 이제 다 시도해 봐서일지도 모릅니다. 그래도 몇 가지는 또 시도합니다!
프런트엔드는 아직 온갖 나쁜 아이디어를 시도하는 중입니다. 그래서 여전히 변화가 많고 알기 어렵습니다.
그루그는 혁명적이라는 새 접근법을 모두 조금 의심해 보길 권합니다. 큰 머리들은 컴퓨터를 오랫동안 다뤄 왔습니다. 대부분의 아이디어는 적어도 한 번은 시도해 봤습니다.
새로운 방법을 배울 수 없다거나 좋은 새 아이디어가 없다는 말은 아닙니다. 하지만 나쁜 아이디어를 재활용하느라 시간을 많이 낭비하기도 합니다. 복잡성의 악령은 새 아이디어를 코드베이스에 마구 집어넣을 때 힘을 많이 얻습니다.
멍청해 보일까 봐 두려워하기
잘 듣습니다! 선배 그루그가 사람들 앞에서 “음, 이건 그루그한테 너무 복잡합니다”라고 말할 수 있다면 아주 좋습니다!
많은 개발자가 멍청해 보일까 봐 두려워합니다. 이를 FOLD(Fear Of Looking Dumb)라고 합니다. 그루그도 한때 그랬지만 극복하는 법을 배웠습니다. 선배 그루그가 “저한테는 너무 복잡하고 헷갈립니다”라고 말하는 건 아주 중요합니다.
그래야 후배 그루그들도 너무 복잡해서 이해하지 못한다고 인정할 수 있습니다. 실제로 그런 경우가 많습니다! FOLD는 복잡성의 악령이 개발자를 지배하는 주요 힘의 원천입니다. 특히 젊은 그루그에게 그렇습니다!
FOLD의 힘을 빼앗는 선배 그루그는 아주 훌륭합니다!
다만 말할 때는 생각하는 표정을 짓고 머리가 커 보이게 하는 게 중요합니다. 큰 머리, 아니면 더 나쁘고 훨씬 흔한, 자기가 큰 머리라고 생각하는 사람이 비꼴 수도 있습니다. 대비합니다.
강해집니다! FOLD는 안 됩니다!
이럴 때 가끔은 몽둥이도 쓸모가 있습니다. 하지만 보통은 유머 감각이 더 유용합니다. 특히 큰 머리가 마지막으로 실패한 프로젝트가 아주 유용합니다. 그런 이야기를 모아 두고 침착함을 유지합니다.
가면 증후군(Impostor Syndrome)
개발하다 보면 자기가 가짜처럼 느껴지는 일이 많습니다.
그루그는 늘 둘 중 한 상태입니다. 눈앞의 모든 것을 지배하며 토르처럼 코드 몽둥이를 휘두르거나, 아니면 자기가 뭘 하는지 전혀 모릅니다.
그루그는 대체로 후자입니다. 그래도 꽤 잘 숨깁니다.
그루그는 실제로 일을 많이 해내는 소프트웨어를 만들었고, 오픈 소스에서도 어느 정도 성공했습니다. 그래도 자기가 뭘 하는지 전혀 모르겠다고 자주 느낍니다! 아주 자주! 아직도 실수로 모두의 코드를 망가뜨리고 다른 그루그들을 실망시킬까 봐 두렵습니다. 가짜입니다!
대부분의 그루그가 가짜라고 느끼는 건 프로그래밍의 본성일지도 모릅니다. 그냥 괜찮다고 받아들이는 게 가장 좋습니다. 모두가 가짜라면 아무도 가짜가 아닙니다.
여기까지 읽은 젊은 그루그라면 개발자로 잘 살아갈 가능성이 높습니다. 답답함과 걱정은 늘 있겠지만 말입니다. 미안합니다.
읽을거리
그루그는 이 글들을 좋아합니다.
마치며
여러분이 말합니다. 복잡성은 아주, 아주 나쁩니다.
원저자 소개
원저자 Carson Gross는 htmx와 hyperscript를 만든 개발자입니다.
이전 글이 없습니다