실습서, 딱 말 그대로다. 읽어보니 80% 정도는 현재 내가 업무에 사용하고 있는 내용이었다. 사용하지 않는 부분이래봤자 큰 덩어리 기준으로 타임리프, 챗GPT 연동 정도일까? 물론 디테일하게 들어가면 일부는 사용하고 일부는 사용하지 않는다 정도지만, 그건 목적에 맞는 옵션 중 하나를 썼기 때문에 다른 걸 쓰지 않았다 정도일 뿐, 큰 맥락에서는 다 쓰는 것들이다.
이게 무슨 의미냐 하면, 이 책이 매우, 매우, 매우, 실용적인 내용들로 가득 차 있다는 거다. 뭔가 개념을 알려주기 위해 기능을 나열한다거나 (시작하는 관점에서는 별로 좋아하지 않는다, 어느 정도 알고 난 다음에는 선호한다. 레퍼런스 역할을 해주니까) 그런 건 아니라서, 정말 책에서 설명해주는 내용을 읽고 이해하고, 하라는 대로 따라해보고, 알려주는 샘플 코드를 넣고 실행해보면 자연스럽게 이게 정말 이렇게 동작하는구나, 하고 느껴질 거다. 그만큼 실무에 딱붙이다. 현재 맡고 있는 프로그램을 처음 개발할 때, 만약 이 책이 있었더라면 훨씬 더 수월하게 할 수 있었다고 자신할 수 있다. 좀더 편하게 일할 수 있었을 텐데, 싶을 정도다.
총 3 파트로 이뤄져 있고, 8장으로 구성돼 있다. 본인 입장에서는 알아두면 좋긴 하지만, 현재는 딱히 쓸 일이 없는 게 5장의 1절과 2절이다. 유용하지 않아서? 아니다, 현재 클라이언트 파트는 SPA로 구현돼 있다보니 쓰지 않아서다. 그래도 뭐 알아둔다고 해서 해가 될 것도 아니고, 전개상 이해해야 하니까 본다. JSP는 써봤으니 됐고, 타임리프는 안 써봤지만, 이번 기회에 알아두는 것도 나쁠 일은 아니다. 사실 쓰는 것만 쓰다보니 수많은 서브 프로젝트들을 다 아는 것도 아니라서, 이런 기회에 알아두면 언젠간 쓰지 않을까?
1장에서는 2절을 특히 잘 알아둬야 한다. DI와 IoC, AOP는 내가 처음 스프링 프레임워크를 접했을 때 살짝 잘못된 설명이 난무하던 때라 첫 단추를 조금 잘못 끼우는 바람에 고생했었다. 아주 명확하고 명쾌하게 설명하고 있으니 잘 이해해두면 많은 부분이 이해될 것이다. AOP는 사실 그 이전에 알게 됐던 개념인데, 90년대 말에 처음 알게 되어 매우 흥미롭게 접근했었던 내용이다. 뭐랄까 필수는 아닌데 없으면 매우 곤란하다는 느낌의 기술로 현대에서는 이게 없다면 본인 기준으로는 서비스를 개발하고 유지관리 하는데 너무나 어려울 것 같다. 그러니 잘 이해해두면 좋다. 앞으로 쓸일도 많고.
2장은 2절의 롬복을 잘 봐두자. 자바 쓸 거라면 아마 필수적으로 활용하게 될 내용이다. 코틀린으로 간다면 아마 안 쓰게 될 것 같지만.
3장은 본인이 참여한 프로젝트가 뭐냐에 따라 갈라지게 되겠지만 아마 MyBatis 아니면 JPA를 주로 쓰게 될 것 같다. 물론 DBMS를 사용한다는 가정 하에서. NoSQL 계열이라면 MongoDB를 주의깊게 봐두면 좋을 것 같다. 사실 NoSQL도 안 써서 알아만 두고 넘겼다.
4장은 그냥 다 잘 익혀야 한다. MSA 사용하는 곳이라면 안 쓸 수가 없다. 물론 gRPC 쓴다면 살찍 궤를 달리 하겠지만. RESTful API는 필수라고 생각한다.
5장은 1절과 3절은 무조건 잘 이해해야 한다. 2절에서 나온 타임리프는 쓸 일이 있다면 알아두면 좋겠지만, MSA/SPA 구조라면 쓸 일이 있을지…
6장과 7장도 무조건 알아둬야 한다. 어떤 식으로 빌드를 할지, 어떤 식으로 배포할지, 그건 프로젝트와 구성원 성향에 따라 달라질 수 있으니, 알아두고 적절히 대응하면 된다.
8장은 최신 트렌드를 반영한 소개로 보인다. 요즘 AI 관심 없는 개발자가 어딨겠는가. 물론 AI를 기반으로 서비스를 개발할 것인지, 아니면 AI를 사용해서 코딩을 할 것인지는 상황에 따라 다르겠지만, 알아둬서 나쁠 내용은 아니고, 오히려 활용하든 안 하든 알아둬야 할 기초적인 내용이다. 그러니 생소할 수 있어도 알아는 둬야 한다.
내용을 읽으면서 느낀 점은 저자는 확실히 업무를 해봤고, 또 가르쳐도 봤다는 거다. 대체적으로 군더더기가 없는 내용으로 채워져 있고, 설명한대로 만들면 실무에 바로 넣어도 된다. 결국 이 내용을 기준으로 무엇을 얼마나 더 강화할 것인지 정도의 차이지, 핵심은 빠진 게 없다. 나만해도 내용 중에 안 쓰고 있었던 걸 발견하게 되어 좀더 파악한 다음 현재 업무에 반영해보려는 생각이 들었다. 다시 말해 유용한 정보가 꽤 됐다.
스프링 부트를 기반으로 프로젝트를 시작하고 싶을 때 이 책이 큰 도움이 되리라 믿어 의심치 않는다. 좋은 책 만났다.
AI, 난리다. 전 세계가 난리고, 한국도 난리고, 주변에서도 난리고, 회사에서도 은근 난리다. 이제 공부하는 걸 더 이상 늦출 수 없다. 친구네 회사는 사내 업무 시스템으로 활용할 거라고 팀까지 꾸렸다. 다른 친구는 아예 AI 솔루션을 만들어 공개까지 했다. 수년 전에는 머신 러닝이 난리더니, 이제는 한걸음 더 나아가, AI가 난리다. 매년 가을쯤에 대전 사이언스 페스티벌을 간다. 애들이 초등학교 다닐 때 애엄마가 이런 게 있더라하고 알려줘서 다니기 시작했는데, 한 3년 전쯤인가, 주체가 AI였고, 이미 학교에서 활용하고 있다며, 고등학교, 대학교 선생, 교수 할 것 없이 나와서 사례 발표를 했더랬다. 우와우와 했지만, 스크립트를 작성하는 게 생소하기도 했고, 저게 되나 싶기도 했고, 뭔가 진입장벽이 높아 보였더랬다.
지금은? 개인적으로는 비슷한 느낌이다. 더 많은 솔루션이 나왔고, 더 고가를 요구하는 것도 나왔고, 성능이 좋다느니, 품질이 좋다느니, 몇몇 분야는 특화된 것들도 나온다 그러고. 코드를 생성하는 수준이 많이 올라가서, 대기업이나 글로벌 기업에서는 인력 감축까지 했거나, 할 거라고, 뉴스에도 나오고, 곡소리도 들려오고 뭐 그랬다.
막연히 거부하는 건 아닌 것 같았다. 언젠가 해야 한다고는 생각했다. 그래서 기회가 왔을 때 이 책을 봤다. 사실 MCP를 친구 통해 듣게 되어서, 우리도 이런 거 해야 하는 거 아닌가 싶어 사전조사할 겸 찾아보다가 발견한 책이다. 이런 류 말고도 다양한 AI책이 나오고 있었는데도 말이다.
우선 내 선입견을 나열해보자. 어렵다? 코드 품질이 좀 그렇다? 업무에 도움이 될 것 같긴 한데, 얼마나 도움이 될지 막연하다? 얘한테 시키느니 내가 짜고 말지?
잔뜩 벼르며 책을 읽어나가기 시작했다.
역시, 0장은 어렵다. 생소한 전문용어 폭격이 시작됐다. 어떤 책이든, 배경지식이 충분하지 않으면 항상 첫 장이 제일 어렵다. 그래서 한 장 한 장 넘기는 게 무척 힘들었다. 친해지려고 애쓰면서 읽어나간다.
1장은 LLM 사용하기 위한 기초 지식의 전달과 사용법을 알려준다. 오케이, 이렇게 하는 거구나.
2장은 RAG, 데이터 인덱싱 하기. 오, 뭔가 따라하기 쉽게 코드가 작성돼 있다. 흠, 이렇게 하면 되는군.
3장은 RAG, 데이터 기반 대화. AI하고 대화하기라니… 직장동료가 AI랑 대화하면서 논다는 게 이해가 된다.
4장부터는 대화하면서 놀기 위한 준비를 어떻게 해야 하는지 알려주기 시작한다. 랭그래프, 대화 목록이구나.
5장 인지 아키텍처, 슬슬 인공지능이라는 느낌이 오기 시작했다.
6장과 7장, 에이전트 아키텍처. 그냥 분신술? 롤플레잉? 그런 인상을 받았다.
8장, 개발자라면 항상 염두에 둘 수 밖에 없는 성능 이슈. 뭐 개발자가 아니더라도, 답을 늦게 받는 게 좋을 리 없다.
9장, 10장, 아, 유료 서비스 통해서 배포해서 사용하고 활용하는 내용이다. 개발자라면 자체 구축을 해보는 것도… 싶지만 이미 잘 된 서비스를 경험하는 것도 많은 도움을 받을 수 있겠다 싶다.
11장, 내가 하고 싶은 게 어떤 건지 저 안에 있는 걸까 고민이 좀 되었다. 단순(?)한 챗 기능은 아닌 것 같고, 결국 보조 개발자 역할을 맡기고 싶은 게 아닐까 싶은데.
부록 A. MCP 서버 구축/활용, 이게 사실상 내가 이해하고 공부해보고 싶었던 분야. 아마도 앞에 나온 내용들을 보지 않았다면 어리둥절 했을 것 같다.
책 내용은 그렇게 어렵진 않다. 사실 책 내용의 절반은 랭체인을 이용해 구현한 코드다. 그러니 설명을 보고 코드 읽기를 시전해보면 이해할 수 있다. 다만, 양에 조금 눌려서 빠르게 읽기는 어렵겠다 싶다. 그리고 머릿속에서 그려보는 것보다는 실제로 실행시켜보는 게 백배 낫다. 그래야 더 잘 이해가 될 테다.
아직은 충분하다 싶을 정도로 지식이 쌓인 것 같지는 않다. 내용과 양을 보면 빨리 읽고 덮을 수도 있을 것 같은데, 이 책의 특성이 실제로 돌려봐야 감이 와서 그런 것 같다. AI쪽 일하는 친구 말이 떠올랐다.
멀티패러다임? 갑작스럽게 책 제목으로 접한 용어다. 처음에는 뭘 말하는지 몰라 책을 읽기 시작했을 때에는 그냥 자바스크립트, 타입스크립트 언어 활용서라고 착각이 될 정도였다. 그런데 저 언어를 중심으로 설명을 한 건 단순히 접하기 쉽고 설명에 적합하기 때문이라는 걸 읽어나가면서 이해하게 됐다.
더욱이 이게 아주 진귀한 뭔가가 아니라 사실상 내가 지금까지 작업해왔던 걸 좀 더 명징하게 표현해주는 용어라는 생각이 들었다. 이게 무슨 뚱딴지 같은 소리일까? 주로 자바와 자바스크립트를 사용하고 있는 내게 멀티패러다임을 이미 하고 있다고? 생각해보면 처음 코딩을 배우고 시작할 때부터 멀티패러다임을 적용해오고 있었던 거였다. 다만 그 개념을 잘 적용하고 인지하고 썼다기보단 별 생각없이 이게 잘 작동하니까, 또는 메모리를 고려해서, 이게 보기 깔끔하니까라는 식으로 적용해왔던 거다.
대학에서 C/C++를 배우고 자바를 배웠다. 자바스크립트는 거의 독학으로 익혀왔고, 이제 막 타입스크립트를 배워보려고 워밍업하는 상황이다. C를 쓰다가 C++를 썼다고 객체지향적으로 내가 코드를 작성했나? 사실은 C 같은 C++를 사용했다. 자바로 처음 넘어왔을 때 진정한 객체지향적인 개발을 했을까? 글쎄올시다다. 과거의 자바 스타일에서 현재 자바 스타일을 생각해보면 과거의 그 자바 스타일로 현재 코딩하고 있을까? 근래는 오히려 함수형으로 작성해보려고 가급적 Optional과 Stream을 활용하고 있다. 기본적으로 절차/명령/객체지향/함수형 그 뭐가 됐든 다 섞어서 코딩하는 중이다.
다시 말해, 나도 모르는 사이에 언어가 제공하는 기술들을 쓰다보면 자연스럽게 멀티패러다임을 적용해 코딩을 하고 있다는 거. 중요한 건 인지하고 이를 의도적으로 의식하고 개발하는 건 아니라는 점이다. 상황에 맞게, 또는 내 변덕으로 이들을 섞어 쓰고 있다. 요즘은 목적에 맞는 걸 사용하려고 애쓰는 상황이긴 하지만.
그렇다면 이 책이 나에게 주는 가치는 무엇일까? 솔직히 기본적으로 목적하는 바에 비해 코드량이 많으면 무조건 버그가 숨어 있다고 생각한다. 그렇기에 가급적 명확하고 적은 양의 코드를 작성해보려고 쓰는 편인데, 이럴 때 기준으로 삼아야 할 게 생겼다. 그런데 그게 그 때 그 때 달라서 애를 먹는다. 그런데 이 책에서는 각 패러다임을 실무적으로 어떻게 적용할 수 있는 알려준다. 아마 체득하면 꽤 유용할 거라 생각한다.
아마도 1장이 가장 난해할 것이다. 가장 생각이 많아지고 책을 덮고 싶을지도 모를 정도로 혼란스러우면서도, 제일 시간을 많이 들여야 하는 구간이다. 아마 코딩하면서 깊게 생각 안 하고 막 쓰고 있었을지도 모르겠다. 그래서 다 아는(?) 내용을 왜 이렇게 구구절절 말하는 거지? 라는 생각이 들지도 모른다. 내 생각엔 그 반응은 정상이다. 그렇기에 그 이면에 숨은, 평소에는 궁금하지 않았던 이 내용을 이해하는 건 앞으로 책을 읽어나가거나, 읽고 난 후 코딩을 할 때 아마 무의식적으로 이걸 생각하면서 코드를 작성하게 될 게 뻔하다. 그만큼 파괴력 있는 기초 중의 기초다.
이게 슬 눈에 익으면 2장에서 현대 개발 언어에서 많이 보는 내용들이 등장한다. 특히 타입 추론, 제네릭 같은 건 빼고 싶어도 뺄 수 없는 핵심이다. 참고로 LISP를 대학 수업 때 배웠고, 과제도 간단하게나마 해봤던 기억이 있다. 가장 인상 깊은 설명은 시스템을 재컴파일과 중단 없이 도중에 정지하고 새로운 코드를 갈아 끼운 다음 정지한 지점부터 재개할 수 있다는 내용이었다. 자동차 렌더링 솔루션인데, 차를 모델링하고 주행시켜보다가 타이어 모델이 맘에 들지 않아 잠깐 중지하고 타이어 모델을 다른 것으로 갈아 끼운 다음, 중단된 순간부터 재개하면 전체 시스템을 중지하지 않고도 바뀐 타이어가 장착된 차가 움직이는 모습을 볼 수 있다고 교수님이 설명하셨다. 그게 얼마나 강렬하게 인상에 남았던지 30년이 지났어도 기억이 난다.
1, 2장에서 설명해온 내용을 기반으로 3장에서 심화 학습하는 느낌이다. 정말로 별 생각없이 사용하던 함수들을 여기서 그 내용을 속속들이 설명하면서 지연 평가 등을 적용한 내용을 알려준다. 아무래도 이해도가 올라갈 수밖에 없다. 끈질기게 설명을 해주니까 더 그렇다.
4장, 비동기를 다루는데, 웹 프론트엔드 개발을 할 때 이해하지 않으면 제대로 할 수 없는 그런 내용을 다룬다. 이 배경지식이 없다면 SPA 같은 걸 이해하는 데 어려움이 있을 것 같다. (사실 그런 개념이 약했어도 얼추 수백 번의 에러를 겪다보면 막연하게나마 이해했을지도 모르겠다)
5, 6, 7장은 실무라고 생각하면 좋다. 실제 업무에 활용할만한 내용들이 많으므로 이건 한 번 읽고 넘길 게 아니라, 진짜 업무를 본다 생각하고 틈날 때마다 하나씩 꼼꼼히 이해해보는 게 좋을 거다. 실력 발전을 위해서라면 말이다. 그렇다고 이게 전부는 아니니, 가이드라인이나 연습문제 정도로 생각해보면 어떨까 싶다.
다시 거듭 말하지만, 별나라 얘기를 하는 게 아니다. 본인이 인지하고 있든 인지하지 않았든, 우리가 늘상 해왔던 내용들이다. 이 책은 그걸 좀 더 체계적이고 인식할 수 있게 잘 가다듬어 설명하고 있다. 비록 큰 관심이 없었던 몇 가지 언어가 중간에 튀어나와 당황스럽긴 했지만, 그마저도 잘 설명을 해주고 있어서 덜 부담스럽다. 오히려 흥미를 느꼈다면 추가로 해당 언어를 익히는 계기가 될지도 모르겠다.
러스트는 역시 어렵다. 러닝 커브가 상당하다. 흡사 스칼라를 배울 때가 생각날 정도다. 그런데 그것보다 더 어렵다. 단순하지 않았다. 정교하다보니 익혀야 할 내용이 많다. 그래서 이지 러스트라고 해서 쉽게 쉽게 읽힐 줄 알았다. 오산이었다. 당연히 다른 책에 비하면 저자의 노력과 역자의 노력이 엿보이는, 그래서 읽으면 그래도 읽혀지는 그런 책이다. 하지만 내용만큼은 잘 기억될만큼 녹록하지 않았다.
러스트를 책으로 접한 건 이펙티브 러스트였는데, 읽다가 완전 멘탈이 나갔었다. 기초가 탄탄하지 않으면 저자가 뭔 얘길 하고 싶어하는지 제대로 이해할 수 없었기 때문이다. 이 책을 읽으려면 초심자부터 시작해야겠구나, 하던 차에 이 책을 알게 됐다. “이지”, 쉽게 러스트를 공부할 수 있겠구나 싶어 덥썩 잡았다.
이 책이 문제가 아니다. 러스트가 워낙에나 어려워서 그런 거다. 근간이 C/C++다보니 피할 수 없는 숙명과도 같은 수준이다. 같은 내용을 여러 가지 방법으로 구현할 수 있는, 마치 자유도 빵빵했던 울티마를 하는 느낌같달까? 그래서 너무나 높은 자유도, 그래서 주어지는 여러 가지 기법들, 문법들, 그걸 쉽게 설명하라고? 저자도 무척 애먹었을 것 같다.
아마 일반적인 책 구성이었다면 PART3를 맨 먼저 간단히 나열하고 (준비해보자~) 16장 러스트 사용하기를 넣은 다음 1~9장을 붙이고 나머지 장들을 후반부 또는 부록으로 마무리했을 것 같다. 이런 책들은 사실 초반 사용하기까지 읽고나면 지친다. 책을 읽어야 하는 게 아니라 환경을 설정하고 샘플을 돌릴 수 있는 환경 설정하는 데까지 실제로 해보지 않으면 그냥 무의미한 텍스트의 나열이 될 게 뻔하기 때문이다. 그래서 흥미가 동하지 않는 경우가 많다.
저자는 그런 점을 알고 있었던 게 아닐까? 웹 브라우저를 통해 온전히 코드에 집중해서 실행해 볼 수 있음을 어필하여 준비 단계랄 게 없다고 어깨 한 번 으쓱 하고 넘어갔다. 오호~
아마 3장까지는 그럭저럭 읽어나갔던 것 같다. 그런데 그 뒤로는 영 진도가 안 나간다. 그 장까지는 읽으면서 러스트가 최신 언어에서 좋다고 하는 건 다 갖다 붙여놨구나, 하는 생각이 들었다. 그래서 비교적 쉽게 이해할 수 있었던 거 같은데, 이 소유 개념과 생명주기 개념 등이 엮이기 시작하면서 진도가 안 나간다. 반쯤 이해를 포기하고 끝까지 글자를 읽어나 보자는 마음에 계속 읽어나갔다. 왜 이렇게 이해가 안 가는 게 많지? 다른 언어에서는 한 가지 타입으로, 때로는 숨겨서, 퉁치는데 여기서는 아주 세세하게 나눠서 접근해야 했다. 이런 방식은 C/C++가 주는 그 자유도와 연관된 게 아닐까 싶다. 자바 세계로 넘어왔고, 스칼라와 자바스크립트, 루비 등에 익숙한 본인 입장에서는 그래서 더욱 까다롭게 느껴졌고, 그러다보니 외우고 이해해야 하는 게 너무 많아서 저자가 계속 얘기하는 내용들이 버겁게 느껴졌던 게 아닐까 싶다.
그래서 결론이 뭐다? 저자는 그런 내용들을 잘 알기 때문에 어떻게든 쉽게 눈높이 교육을 하기 위해 노력한 것이다. 그 노력과 그 결과물에는 찬사를 보낸다. 공부해보겠다고 개발자 가이드 서적을 구매해서 보자마자 머릿속이 하얘지는 경험을 한 사람으로, 정말 이것보다 더 쉽게 설명이 가능했을까 싶긴 하다.
“이지”하지만 단시간에 읽을 수는 없어 보인다. 그만큼 방대하기도 하고, 외우고 익숙해져야 할 개념도 많다. 하지만 기초를 원한다면 이 책이 매우 적합하다는 생각이다. 믿기 어렵다면, 개발자 가이드를 보라. 양에 질릴 테다. 그래서 추리고 추려 쓴 이 책이 좋다.
작년에 이미 알고리즘 책 한 권 봤는데, 왜 또 이걸 읽고 있는 거지? 사실 이유는 두 가지다. 첫 번째는 아무리 봐도 안 쓰니까 자꾸 잊어버려서 계속 봐야 한다는 것이고, 두 번째는 “그림으로 개념을 이해”한다는 표현에 꽂혀서다. 그래서 이 책을 보자마자 아이들에게 이런 책이 있다고 뀌띔했다. 그림으로 쉽게 이해할 수 있다면, 아이들에게 한 번 읽어보라 싶었다. 수업 중에 정보가 있고, 그러면 어쩔 수 없이 알고리즘은 배울 테니, 도움이 되지 않을까, 하는 막연한 생각이 들어서다.
그런데 첫 번째 이유는 나름 타당해서 문제가 없었는데, 두 번째는 문제가 생겼다. 중학교 정보 서적에서 알고리즘을 봤는데, 굳이 이런 전문도서의, 그래도 입문서격인 책이, 사실 필요없는 수준이라는 점이다. 섣부른 판단일지도 모르겠지만, 적어도 교과서 내용에서는 이 정도 수준까지 요구하지는 않을 거라는 생각이 들었다. 정보가 재밌고, 코딩이 재밌고, 그래서 주어진 문제를 해결하는 게 재밌어서 알고리즘을 제대로 공부해보자 하지 않는다면, 이 정도 난이도의 책도 아이들에겐 마냥 어려운 책일 수밖에 없겠구나 싶었다. 그래서 두 번째는 포기했다.
여기서 문제, 작년에 본 책을 다시 꺼내 슬슬 넘겨보며 읽어봤다. 그 책도 충분히 잘 만든 책이라 생각했는데, 이 책과는 결이 다른 게 눈에 보였다. 지난 책도 충분히 “기술”적으로 접근해서 잘 설명해주고 있다 생각했는데, 아무래도 그건 전산인의 눈으로 봐서 그랬을 수도 있겠다는 생각이 들었다. 저자는 프로그래밍을 취미로 시작했다가 알고리즘을 책으로 접했다가 방대한 양에 포기했다가 훌륭한 교수를 만나 그 기본 개념을 알아가기 시작했다고 말한다. 그러면서 본인이 “시각적으로 학습하는 것을 선호하고, 그림으로 설명하는 것에 익숙”하다고 말한다. 이게 이 책의 정체성을 설명하는 중요한 표현이라 생각한다.
처음 책을 펼칠 때 나의 기대는 만화책같은 느낌이지 않을까 하는 생각이었다. 곧 그건 잘못된 생각이라는 걸 알게 됐지만, 적절한 그림 표현과 문장들은 해당 내용을 전달하는 데 있어 매우 효과적이고, 심지어 코드와 해당 코드 상황에서의 그림 표현은 이해를 도울 뿐만 아니라, 머릿속에 콱콱 박아넣는 듯한 인상을 줬다. 괜히 “아마존 프로그래밍 언어 분야 베스트셀러”가 아니었다.
알고리즘의 소개를 통해 배경을 알려주고, 선택 정렬과 재귀, 퀵 정렬을 거쳐 해시 테이블과 너비 우선 탐색, 트리, 균형 트리로, 다익스트라 알고리즘, 탐욕 알고리즘, 그리고 동적 프로그래밍과 KNN 알고리즘으로 나아간 다음, 더 공부해야 할 것에서 최근 핫한 내용들과 연결되는 알고리즘들을 추가로 언급한다.
내용이 빈약한 것 아닌가? 하는 생각이 든다면, 그건 과욕이다. 사실 학술적으로 접근하면 한 장 한 장 그 분량이 대단해서 입문서가 아니라 전공서적이 되어버릴 테니까. 이만큼이나 다루는데도 핵심만 쏙쏙 짚어주면서도 설명이 쉽고 간결하다. 주요한 지점에서는 그림과 결합하여 이해하기 쉽게 전개한다. 그래서 막힘이 없기에 술술 잘 읽히는 느낌도 있다.
한 장 한 장 끝날 때마다 배운 내용을 요약하고, 연습문제를 낸다. 그런데 그 문제가 꽤 현실적이라 문제를 위한 문제로 느껴지지 않는 것도 대단하다면 대단하다. 중간 중간 나온 팁도 매우 유용하다.
처음 읽었을 때 꽤나 신선하게 다가온 설명 중 하나는 “메모리가 작동하는 방식”이었다. 메모리를 서랍에 비유하니 재밌었다.
허프만 코딩도 들어는 봤고, 쓰기도 했지만, 사실 동작 원리를 이해하고 쓰진 않았는데, 이 책에서 설명하는 내용을 보고 이제야 기초적인 이해를 한 것 같다. 사실 그냥 쓰기만 할 거라면 몰라도 되지만, 프로그래밍에 응용할 거라면, 알아두는 게 무척 도움이 될 만하다.
실제로 그래프, 특히 트리 개념은 알게 모르게 엄청나게 사용하고 있기에, 이해하는 게 절대적으로 필요하다. 그걸 이렇게 쉽게 설명하니 대단하다. 다익스트라 알고리즘은 매번 볼 때마다 어려웠는데, 이 책에서 너무 잘 설명해줘서 무척 도움이 됐다.
이 책에서 앞서 설명한 알고리즘으로 그 다음 알고리즘을 구성하거나 설명하는 식의 패턴이 해당 내용을 이해하는 데 큰 도움을 줬다. 보통은 그런 연결성을 유추하거나 지나가는 말 중에 하나로 취급할 텐데, 여기서는 앞에 알고리즘이 여기서 어떤 영향을 주고 왜 이렇게 되었는지를 아주 요긴하게 쓰고 알려 준다. 때로는 비교를 통해 왜 이게 되고 이게 안 되는지도 알려 준다. 이렇게 해주니 이해가 쉬울 수밖에. 과거 강의 시간에 배웠던 방식과는 달라서 너무 좋다. 그 때 이렇게 배웠다면 얼마나 좋았을까… 뭐 내가 게으른 탓이지만.
거듭 설명하지만, 입문서다. 이걸로 해당 알고리즘을 다 알았다고 하면 안 된다. 적어도 그 알고리즘을 깊이 이해하기 전, 기본 개념을 잡는 데에는 매우 유용한 책임을 주지해야 한다. 그렇다고는 해도 너무 가볍게 볼 필요도 없다. 이 책을 써서 프로그래밍을 한다고 해도 문제 될 건 없어 보인다. 이해하고 짜는 것도 이해 안 하고 대충 써서 짜는 것은 엄연히 다르다. 그 결과가 다르다. 결국 같은 결과를 얻더라도 O(log n)으로 나올지 O(n!)으로 나올지는 선택의 문제다. 올바른 선택을 위해서는 이 책을 추천한다. 후회하지 않을 거다.
책을 다 읽고 나서 느낀 점이다. 문득, 대상 독자는 고교 과정을 이수한 사람이라면 충분히 이해할 수 있는 내용이라고 판단했다. 다만, 수학 공부를 한 지 좀 시간이 지나서 희미한 개념만 알고 있다면 좀 갑갑하겠다는 생각은 들었다. 내가 그랬으니까.
뜬금없이 왜 이런 얘기를 하냐고? 2장에 나오는 필수적인 수학 내용에서 벡터 연산 내용이 쉽게 이해되지 않아서다. 방향과 힘의 크기를 나타낸다는 지식은 있다. 수학보다는 물리 때문에 더 기억하고 있는 내용이다. 그런데 내적과 외적 용어가 나오니 내가 이런 걸 공부한 적이 있었나 싶을 정도였다. 이를 테면, 내게는 이런 지식들이 허들이 됐던 거다.
그렇지만 비교적 내용을 쉽게, 적당히 설명한다. 아무래도 모교 선생님들에게 감사를 표한 걸로 봐서 직간접적으로 도움을 받았던 게 아닐까 싶다. 왜냐하면 내용 전달하는 게 지식의 나열이 아니라 “설명”하는 문장들로 가득했기 때문이다. 속된 말로 치고 빠질 포인트를 잘 잡았다는 느낌? 다시 말해, 선생님이 학생들을 가르치기 위한 교습법대로 진행했다는 느낌이 남아 있다.
1장은 개발 환경을 구성하는 방법을 개략적으로 알려주고 게임 세계를 이해하기 위한 밑밥을 깔아놨다. 개념을 전달하기위해 간단히 적어두다보니 본인 입장에선 유니티를 처음 써보는데 어떻게 해야 할지 감이 오지 않아 애를 먹었다. 쉽게 되지 않다보니 스트레스 받을 것 같아서 과감하게 설치하고 띄워만보고 계속 책을 읽어나갔다. 읽고 나면 어떻게든 되겠지 싶어서다.
2장은 필요한 수학과 물리 개념을 알려준다. 게임의 가장 기초적인 내용과 이와 관련된 수학과 물리 개념들을 풀어나가는 솜씨가 괜찮았다. 때로는 너무 쉬운 거 아니야? 싶을 정도의 수준이지만 쉽고 깔끔하게 설명을 해주면 이해하는 데 무척 도움이 된다. 본인은 아는 내용도 꽤 됐지만 그럼에도 재밌게 읽어나갈 수 있었다. 삼각함수, 사인, 코사인, 탄젠트. 그림과 간략한 설명을 해주니 이해하는 데 무리는 없었다. 만약 고교 졸업 또는 일반 수학을 공부하고 대학 졸업한지 얼마 되지 않았다면 전혀 무리 없이 이해할 수 있는 수준이다. 앞서 얘기한 것처럼 벡터 연산과 내적, 외적은 조금 어렵다는 느낌이었지만, 갓 졸업한 사람들에게는 큰 어려움은 아닐 테다.
3장은 매우 중요한 개념을 알려준다. 이건 놓치면 안 되는 부분이다. 시간의 불연속성. 자주 게임을 하면서 놓치기 쉬운 부분일 듯 싶다. 하지만 절대 놓치면 안 되는 부분이다. 황당한 게임 상황을 겪지 않으려면 잘 고려해야 하는 부분인데, 막연하게만 알던 부분을 비교적 깔끔하게 이해할 수 있었다. 자료구조는 배웠으니 됐고, 알고리즘은 항상 볼 때마다 까다롭다. 기초적인 알고리즘은 대략 알고 있지만, 잘 안 썼던(그런데 왜 써야 하는지도 잊어버렸던) 알고리즘들을 다시 살펴보게 됐고, 특히 게임 세계에서 많이 쓴다는 알고리즘은 이번에 처음 보게 됐다. 특히 충돌 처리 알고리즘. 보통 학교에서는 이런 것보다는 정렬, 탐색 알고리즘을 더 비중있게 배웠던 것 같다. 또는 암호화 알고리즘이라든지. 그런데 충돌 처리 알고리즘은 생소했다. 그래서 이해하려고 더 애쓴 것 같다. 완벽히 이해한 건 아니니, 추가로 책이나 인터넷에서 검색을 해봐야 할 것 같다.
4장은 방법론을 얘기하는데, 객체 지향 개념을 리마인드한 것 같다. 그것도 어렵지 않게 말이다. 내공 없이는 저렇게 풀어나가기 어려울 텐데, 라는 생각이 들었다. 디자인 패턴도 몇 가지 다시 보거나 새로 알게 됐고, 안티 패턴에서 “최적화 안 하는 게 답”이라는 맥락의 표현도 봤다. 다른 책에서 이른 최적화는 독이 된다는 내용과 통하는 것 같다. 사실 실무에서도 많이 느끼는 부분이기도 하다. 왠만한 건 머신 성능이 좋아서 잘 받쳐주니까 돌아는 가게 하고, 필요한 부분을 최적화 하면서 전반적으로 균형을 맞춰주는 게 효율이 좋았다. 내용을 잘 파악해야 개선이 되는데 그런 거 없이 섣불리 최적화 했다가 문제가 많이 생기는 직간접적인 경험도 해봤으니까.
어떻게 보면 4장도 이미 다른 최적화 관련 책이나 기술 서적에서 많이 언급되는 내용들을 가급적 평이하게 설명하는 것도 같다. 이런 내용을 보면서 선생님들의 도움이 아니었을까 하는 추측을 해봤다. 정말 그랬는지는 알 수 없지만.
간만에 맘에 드는 게임 개발 입문서를 봤다. 가끔 게임 개발을 해보고 싶어서 책을 찾아보면 내 입장에서는 중급자를 위한 내용들로 가득 찬 책들만 있었다. 비교적 입문서 성격을 가졌다 해도 목차를 보면 이미 필드에서 뛰고 있는 사람들을 위한 책처럼 보였다. 비 게임 개발자로서 허들로 느낄 수 밖에 없었는데, 이 책은 매우 좋은 입문서 역할을 해줄 것 같다.
여기 내용을 숙지하고 조금씩 게임 개발 첫 발을 뗄 수 있을 것 같아 즐겁다. 저자들의 목표가 달성되어가는 소리가 들리는 듯하다.
오판이다. 20년 전까지는 C/C++ 개발일을 그래도 좀 했고, 러스트가 나온지는 좀 됐지만, 실무에서는 해본 적이 없고, 회사에서 이 기술을 이용해 서비스를 개발했다고 하길래 그 코드를 읽고 이해하기 위해 공부를 해야겠다 생각해서, 이 책이 최신 서적이다보니, 유용한 팁도 알 겸해서 골랐는데, 완전이 오판했던 셈이다.
일단 초반은 너무 어렵다. 여기서 사용하는 기술용어도 익숙하지 않은데, 설명하는 내용도 최소한 초심자는 벗어난 상태여야, 게다가 이 언어로 뭔가를 좀 만들어 봤어야, 심지어 고민도 꽤 해놨어야 이해가 될만한 내용들로 가득 차 있다.
책 머리에 있는 베타리더들의 글을 먼저 읽어봤어야 했다. 정확히 이해하는 리더들의 조언을 새겨 들었어야 했다. 나같은 러스트 초심자(그래도 자바/스칼라 등을 20년 넘게 썼는데도)가 읽기에는 난이도가 높은 중급자용임을 미리 인지했어야 했다. 그만큼 시작은 어렵다.
1장 타입과 2장 트레이트는 이 책의 근간이다. 물론 세간에 알려진 것과 같이 메모리 관리에 관한 부분이 뛰어나다는 점도 중요하지만, 읽자마자 가슴을 두근거리게 만든 표현이 있다. “‘러스트는 어떻게 타입 시스템을 통해 프로그램 컨셉을 디자인하는가’를 보여주는 단적인 예” 다시 말해, 타입 시스템을 활용해 개발자의 의도를 손쉽게 표현할 수 있다는 점이고, 어느 정도 안정성을 보장도 해준다는 거다. 이거 무시 못할 특성이다. 자바 등으로 제아무리 잘 디자인해놔도 의도를 잘못 이해하고 사용하는데 정말 별의 별 경우를 다 방어하도록 작성하지 않는다면 잘못된 사용을 막을 방법은 사실상 없으니 말이다. 그런데 이게 가능하다? 놀라운 일일 수밖에 없다.
그나마 잘 읽히는 편인 부분이 2장 트레이트였다. 이유는 최신 언어에서 차용해서 사용하는 메서드 방식들이 나오고 있어, 쉽게 이해되는 부분이었다.
3장 주요 개념과 4장 의존성, 5장 도구 활용도 사실상 CS 이론과 그 응용에서 어떻게 러스트와 결합되어 처리되는지를 알려주는 셈이라 매우 중요하면서도 흥미로운 주제다. 하지만 러스트스러워야 한다는 점에서 이해하기 벅찬 부분도 분명히 있었다.
만약 C/C++ 계열 언어에 친숙하고 최소한 최신 트렌드의 언어를 하나 이상 이해하고 있는 초심자(?)라면 이 책을 읽는데 나만큼 난해하지는 않았을 거라 생각한다. 이유는 다른 게 없다. 개인적으로 C/C++ 문법이 꽤 난해하다는 인상을 가진 내게 있어 코드 읽기가 쉽지 않았던 탓인데, 그런 표현이 익숙하다면 저자가 설명하는 내용을 코드와 매치시켜 이해하는 데 어려움이 덜할 거라고 생각하기 때문이다. 마치 스칼라를 처음 익혔을 때 느꼈던 막막함, 첫 컴파일 성공에 3일이 걸렸던 그 기억과 닮았다.
1장을 읽으면서 바로 “러스트 프로그래밍 공식 가이드”나 “프로그래밍 러스트” 초급자용 도서를 동시에 공부해야 하나 고민이 되었다. 회사 일이 바쁘다보니 더 이상의 시간을 내는 게 어려워 병행하진 못했지만, 기초부터 습득해서 기술용어와 컨셉에 익숙해지면 다시 도전해서 이해해보려 한다. 베타리더 언급 중 “러스트 언어를 제대로 이해”하고자 하면 읽어보라고 권유하는 데에 100% 동의한다. 그만큼의 가치가 있다. 아마 설계를 하고 핵심 내용을 군더더기 없이 구현하려 했을 때 난감했던 지점들을 이 책이 명확하게 설명해주고 있기 때문이리라.
클린 코드. 말은 쉽다. 읽기 좋고, 간단하고 직관적이며, 그럼에도 좋은 동작을 보여주는 코드. 사실상 실무에서 이런 코드를 접하는 건 하늘의 별따기다. 솔직히 아직까지 클린 코드라고 볼만한 코드를 본 적은 없다. 심지어 본인도 그런 코드를 짜본 적이 없다. 다시 말하자면, 말은 그럴 듯한데, 이게 클린 코드다라고 할 만한 전형을 본 적이 없다. 그래서 뭐가 클린 코드인지 머릿속에 잘 그려지지 않는다.
이 책을 보기 전에 클린 코드 바이블 격인 책을 본 적은 있다. 그런데 내 머릿속에 남아 있는 게 별로 없다. 본인이 제대로 안 읽었던지, 너무 이론 중심적이었던지, 아무튼 없다.
뭔가 써먹을 만한 걸 모아둔 책이라고 한다. 208가지나 실었다. 뭐라도 하나 건지면 다행이란 생각이 들었다. 그래서 일단 펼쳐 읽기 시작했다. 구성은 매우 간단하다. 문제와 해결, 그리고 설명. 208번 반복하고 있다. 이를 이해시키기 위해 좀 장황하게 설명을 하고 시작했다. 갑자기 전단사? 수학 용어가 나온다. 아, 물론 프로그래밍의 기본은 논리와 수학이다. 이를 무시하는 건 아니지만, 갑작스레 수학 용어를 자주 반복해서 사용하다보니 복잡한 느낌을 받는다. 여전히 수학은 잘 모르겠다.
전단사와 더불어 매우 자주 언급되는 표현은 “빈약한”이다. 원서에서 어떤 단어를 빈약한으로 번역한 걸까? 그냥 번역기에 돌려보면 “빈약한”은 “poor”로 번역하는데, 정말 이 단어였을까? 다른 단어이진 않을까? 궁금해진다. 차후에 원서를 보게 되면, 한 번 신경써서 봐야겠다 싶다.
1장과 2장은 좀 어려웠다. 원래 책에 서두와 첫 번째 장이 제일 어렵다고는 하지만, 희한하게 잘 읽히는데 어려웠다. 아마 이해해야 할 핵심 내용인지라 그런 인상을 받았을지도 모르겠다. 인내심을 갖고 읽어내린 다음 3장부터 이제 실질적으로 필요한 레시피가 나오기 시작한다.
전반적으로는 이렇게 평가할 수 있겠다. 어떤 레시피는 아하, 하고 감탄할만 하고, 어떤 레시피는 묘했고, 어떤 레시피는 아닌 것 같은데 싶었고, 어떤 레시피는 무슨 얘길하는지 잘 이해가 되지 않았다. 다시 말해 208가지 전부가 나에게 다 이해가 되고, 필요했으며, 적합한 건 아니었다는 얘기다. 그러나 상당수가 내 생각과 비슷했고, 도움이 될 만한 내용들이었다.
감탄할 만한 레시피는 3.2 객체의 본질 파악하기를 그 예로 들 수 있겠다. 완벽히 이해가 된 상태는 아니지만, 필수 동작이 객체를 식별한다는 설명 그 자체는 내게 울림을 줬다. 이를 잘 소화해내서 체화하는 건 내 몫인지라 고민이 많이 필요한 내용이었다.
묘했던 레시피는 4.1 작은 객체 생성하기다. 보통은 이름을 저장할 변수를 정의하면 String name으로 끝난다. 그런데 그렇게 하지 말고 Name을 정의하고 Name name으로 사용하라고 한다. 의도는 이해가 되지만 이게 과연 현실적인가라는 의문은 남는다. 이렇게 사용한 객체를 DB와 연관짓게 되면 변환 절차를 거치도록 추가 작업을 해야 하는데, 이게 과연 현실적인가 묘했다.
아닌 것 같은 레피시는 6.11 괴상한 조건문 재작성하기다. if (42 == abc) 라고 하지 말고 if (abc == 42) 라고 하라는 얘기다. 왜 이상할까? 꽤 오랫동안 후자 방식으로 했을 때 실수로 abc = 42와 같이 사용하거나 했을 때 문제를 알아차리지 못하고 실행될 수 있고, 이로 인해 오류가 발생할 수 있으니 문제가 되지 않도록 전자처럼 코드를 작성하라고 조언을 받아왔다. 꽤 여러 책과 글에서 접했던 내용이었다. 그런데 이렇게 하지 말라고 얘길하는 게 아닌 것 같다는 생각이 들었다. 둘 다 나름의 논리를 갖고 있으니 결국 받아들이는 건 본인이니 본인이 잘 판단해야 할 문제긴 하겠지만 말이다.
무슨 얘긴지 이해가 안 되는 레시피는 16.1 객체 ID 피하기다. 실질적으로 처리하는 모든 데이터는 DB와 밀접한 관계가 있다. 값을 처리해서 DB에 저장하거나, DB에 저장된 값을 읽어와 주어진 처리를 한 다음 다시 저장한다. 그렇기 때문에 거의 모든 객체에는 ID가 존재한다고 볼 수밖에 없다. 그래서 이 부분은 잘 이해가 되지 않았다. 잘못된 내용은 아닐 테고, 저자가 얘기하는 바를 제대로 이해하고 받아들이지 못한 것 같아 좀더 연구할 필요가 있는 내용일 테다.
각 경우에 맞게 하나씩 레시피를 그 사례로 들었지만, 그런 유형들이 여러 개 있다. 그래서 이 책은 한 번 읽고 책장에 꽂아두는 책이 아니다. 다양한 경험을 할 수록 이 책에서 적용 가능한 레시피를 찾아 써보는 게 좋다. 그리고 가끔 레시피 하나를 뽑아 그 내용을 곱씹어보는 게 좋을 만한 책인 듯도 싶다.
다만 아쉬운 점은 다양한 레시피를 소개하고 있고, 필요에 의해서 어떤 레시피들은 적절하게 설명을 달아놨지만, 어떤 레시피는 그 설명이 상대적으로 빈약해서 관련 자료를 더 찾아봐야 하는 경우도 있었다. 즉, 만병통치약처럼 볼 수는 없는 내용이 있다. 이 점은 주의해야 한다.
현재 진행 중인 프로젝트에서 이 레피시들 중 적용할만한 게 있다. 다만, 그대로 적용하기엔 무리인 것들도 있다보니 점진적으로 적용할 수 있는 방법을 찾아야 한다. 그래도 개선 방향에 써먹을만한 내용(특히 16장 섣부른 최적화, 17장 결합도, 20장 테스트, 21장 기술 부채, 22장 예외 등)이 많으니 차분히 활용해 볼 생각이다.
저자는 이 책 1.4 왜 클린 코드인가요? 에서 읽고, 이해하고, 유지 보수하기 쉬운 코드를 의미한다고 적어놨다. 머리로는 알겠는데, 마음 속 깊숙이 우러나오는 느낌은 아니다. 저자의 말을 이해할 수 있는 그날까지 더 공부해야겠다. 이런 나침반같은 책들을 읽으면서.
나에게 이 한 줄이 무척이나 큰 의미로 다가온다. 허투루 할 수 있는 말이 아니다. 적어도 어느 정도 기술적으로 궤도에 오른 사람이 할 수 있는 말이라 생각한다. 그것도 저자가 “마치며”의 첫 문장으로 쓴 표현이다. 그 다음으로 쓴 말을 보자.
"그 언어나 기능이 왜 필요했는가 하는 것을 생각하면 이용하는 상황이 쉽게 보일 수 있고, 다른 기술에서는 필요했던 것이 이 기술에서는 어떻게 되는지 생각해볼 수도 있습니다."
전산학을 공부하면서, 실무를 하면서, 자연스럽게 느낄 수 있었던 바로 그것이다. 왜 이 기술이 존재하는지, 왜 이렇게 만들 수밖에 없었던 것인지, 왜 이래야만 했는지. 바로 그러한 것들을 집약한 표현한, 단 하나의 글자가 ‘왜’라고 생각한다.
아무리 좋은 기술이라도, 한 시대를 풍미하는 기술이라도, 누가 봐도 쉽게 쓰였다는 기술이라도, 이 ‘왜’라는 질문에 답할 수 없다면, 애석하게 와닿지도 않고, 그 기술을 쓰고 싶은 생각도 들지 않았다. 나의 의문에 답을 줄 수 있는 기술이어야 이해도 되고 사용하기도 비교적 수월했고 또 그걸로 문제를 해결할 수 있었다. 그렇지 않은 기술은 아무리 봐도 이해가 되지 않았고, 사용하더라도 문제 투성이라 결국엔 안 쓰게 되었더랬다.
그런데 저자가 그 의문이 새 기술을 습득하는 요령이라고 친절히 알려준다. 그래서 그랬나? 이 책은 근래 읽었던 책 중에서 가장 빨리 읽혔고, 쉽게 이해가 갔고, 그래서 내게 딱 알맞을 정도의 길라잡이 역할을 해줬다.
근래 회사에서 주로 Spring Boot / Java로 백엔드 개발을 하다가, 여러 가지 이유로 프런트엔드 개발도 병행하고 있다. 거기서 사용하고 있는 기술이 Node.js와 React.js다. 앞서 리액트 경우에는 굉장히 초심자가 읽기 좋은 책을 접할 수 있어서 즐겁게 보며 궁금했던 점들을 해소할 수 있었다. 초심자가 읽기 좋은 책, 그래서 리액트에 초점이 맞춰져 있기 때문에 그 자체만으로는 도움이 많이 되었지만, 그 근간에 있던 Node.js에 대한 건 상대적으로 빈약할 수밖에 없었다.
그런데 이번에는 Node.js다. 이 방대한 걸 전부 백과사전식으로 나열하며 설명하지 않는다. 어떻게? 마치 업무에 처음 적용해보려는 것같은 느낌의 설명이다. 철저히 업무에 활용하기 위한 방식이다. 그렇기 때문에 소소할지도 모르지만 확실히 꿀팁이 많이 들어 있다. 본인이 써봐서 이해하고 있는 팁들을 알려주기 때문에 같은 패키지들을 확인해보고 싶은 욕구가 생긴다. 심지어 도입해 쓸 만한 것도 많으니 이렇게 유용할 수가 있을까?
게다가 확실히 이해하고 쓴다는 생각이 들 정도로 핵심적인 내용들 위주로 설명하고, 예제도 점진적으로 (필요에 의해 반복하면서) 작성해가면서 차이점을 명확히 알 수 있도록 해준다. 장과 장 사이를 넘어갈 때 부담스럽지가 않다. 그러면서도 이해가 쉽게 쏙쏙 짚어가며 알려 준다. 아주 좋은 방식이다. 그래서 평소보다 술술 잘 읽히는 기술 서적 중 하나라 생각한다. 뭔가 특별하고 대단한 기술을 알려주는 것은 절대 아니다. 실무 도입 시 필히 봐둘만한 형식이랄까?
왜 나에게 이 책이 더 크게 와닿았을까? 그것은 현재 내가 하는 업무와 아주 밀접하게 연결돼 있다. 현재 맡고 있는 프런트엔드 프로젝트는 프런트엔드 전문 개발자가 React.js를 처음 공부하면서 개발했다. 꽤 장기 개발을 했기 때문에 초창기 작업한 코드와 근래 작업한 코드가 스타일도 그렇고 수준도 그렇고 차이가 난다. 그래서 여러 가지 형태로 구현돼 있는데, 천천히 업그레이드를 하다보니 코드 방식이 여러 개 섞여 있는 셈이다.
그걸 중간에 받아서 하려다보니 꽤 애를 먹고 있다. Node.js에 익숙치 않다보니 이런 것들이 왜 필요했던 것인지 기초적인 것들을 제대로 알지 못한 상태에서 오로지 논리적으로 이렇게 되지 않을까 하고 건드리면서 해결해나가고 있는 실정이다. 이미 좋은 샘플이 많이 있으니 복붙 후 수정 스타일로 작업하고 있달까? 그런데 이 책을 읽으니 작업하면서 막연하게 느껴졌던 애매함과 몰이해가 어느 정도 해소되었다고 하면 될 것 같다. 다시 말해, 제대로 몰랐던 걸 제대로 알아가기 위한 기초를 알게 되었달까?
CORS 관련해서도 문제가 생겼고, 이를 해결하기 위해서 작업을 했다는 것만 알고 있었지, 이 책에서 설명하는 정도로 이해하진 못했던 것 같다. 그랬으니 이 문제를 해결하기 위해 회사 동료가 했던 업무가 잘 이해되지 않았는데, 이참에 이해하게 됐다. 그리고 당시 담당 개발자가 했던 말들이 이제야 조금 이해할 수 있게 되었다. 개발에 프록시 서버가 왜 필요했는지, 프로덕션일 때 추가로 데브옵스 개발자가 어떤 설정 작업들을 했었던 것인지 이제 이해가 되기 시작했다.
SPA 추세는 이해했지만, 왜 복잡하게 구성하고 진행이 될 수밖에 없었던 것인지. 패키지를 업그레이드 했다가 문제가 생겨서 롤백하거나, 그 문제를 해결하기 위해 해당 패키지 문서에 서술된 업그레이드 시 해야 하는 업무 내용을 읽고 따라 반영해본다든지. <Routes>, <Link> 등을 사용해서 구성해야 했던 이유들. 회사 개발 환경 이전으로 방식을 바꾼 뒤에 웹브라우저에서 페이지를 열어서 확인하다 리로드 시도했을 때 왜 에러가 발생했던 것인지. 그런 실무에 밀접하게 연결된 내용들을 컬럼을 통해 전달해주는 방식도 마음에 들었다. 그것도 적절한 시간에 적절한 공간에서 말이다.
확실히 난해할 수 있는 표현을 이렇게 깔끔하게 정리해서 알려주는 것도 대단하다고 생각한다. 저자의 능력이기도 하겠지만, 리뷰를 해준 동료의 센스에도 감탄하게 된다. 확실히 대단한 가이드가 적용된 듯한 인상을 받았다. 이렇게 깔끔할 수 있는 건가?
책에서 나에게 가장 의미 있는 장을 몇 개 꼽아보라 한다면 과감히 3장, 4장, 6장, 8장, 이렇게 4개 장을 꼽겠다. 이유는 다음과 같다.
3장 – Node.js와 모듈. CommonJS과 ECMAScript 모듈의 활용 관점에서의 설명과 package.json 관련 설명 (아주 도움이 되었다) 4장 – Node.js에서의 비동기 처리. 동기와 비동기, 이와 관련된 콜백, 프로미스, async/await, AsyncIterator 등을 비교 설명 6장 – 익스프레스를 이용한 Rest Api 서버 웹 서버. 점진적으로 개선해나가는 익스프레스 기반 Rest Api 서버 및 웹 서버의 비교 설명 8장 – 애플리케이션 운용과 개선. 지금 내가 하고 있는 최고 난이도 업무들과 연관
나머지 장들도 확실히 도움이 많이 되었지만, 위 4개의 장들의 설명들은 내게 있어 뿌옇기만 했던 점들이 점점 더 실체를 갖고 나에게 제대로 보이기 시작한 지점들이라 생각한다. 이 내용들을 바탕으로 더 많이 파보면 멀지 않은 미래에 확실히 이해할 수 있게 되지 않을까 행복회로를 돌려본다.
반대로 이 책의 장들 중 공부할 때 고비로 다가온 것들은 무엇일까? 7장과 아이러니 하게도 바로 8장이다. 여기가 가장 고비였다. 이유는 7장의 경우 거의 써보지 않은 패키지나 기술들이 많았고, 테스트 부분이 약한데, 이 부분을 건드리다보니 머릿속이 복잡해져서, 사실 돌려보지 않으면 감이 잘 안 오는 부분들이라 그랬다. 당장 현업을 해야 하다보니 샘플격으로 만들어 돌려볼 시간이 잘 안 나다보니 글로만 이해하려고 해서 좀 그랬나보다. 8장은 성능 튜닝이 흥미로우면서도 많이 겪어보지 못한 상황이다보니 이해가 더뎌서 그랬던 것 같다.
그럼 책에 문제가 있는 거 아닌가, 하고 오해를 할 수도 있겠다. 그런데 그건 진실이 아니다. 내게 어려웠다는 건 내가 그 부분이 굉장히 약하다는 얘기가 되고, 이건 내가 학습을 더 진행해야 하는 부분임을 알게 해준 거라 읽을 당시엔 힘들었어도 진행할 방향을 알게 되어 무척 다행이라 생각한다. 솔직히 전부다 쉽게 이해가 되는 책이라면, 굳이 구해 읽을 필요가 없다. 시간과 돈 낭비다. 약한 부분을 보완해줄 수 있는 책을 찾는 게 훨씬 효과적일 테니까.
마지막으로, 저자가 한 말 중 이 책을 정리발언하는 내용이 있어 인용해보고자 한다.
"이 책에는 '왜'를 알기 위해 간단한 기술의 설명뿐만 아니라, 제가 본 역사와 얻었던 경험, 생각들을 가능한 많이 담았습니다."
회사를 다니는데 하나의 프로젝트를 혼자서 계속 하는 경우는 드물지도 모른다. 보통은 하나의 프로젝트를 여럿이서 나눠 하면서 각자 맡은 부분을 작성하고 있을 거다. 당연히 GIT 같은 형상관리툴도 쓰고, GitHub 같은 걸 통해 코드리뷰도 진행할 것이다. 페어 프로그래밍을 하는 경우도 있을 것이고… 심지어 ChatGPT를 통해 작성된 코드를 참고해서, 아니면 수정해서 사용하는 경우도 있을 것이다.
그렇게 작업을 하다보면, 나의 코드와 남의 코드 사이에 발생하는 괴리감을 느낀다. 명시적인 코딩 컨벤션이 있다면 그 정도는 덜할 텐데, 암시적인 코딩 컨벤션이 존재하고, 그걸 철저히 준수하지 않아서, 이전 코드와 지금 코드 간의 괴리감도 많이 느낄 것이다. 또한 리뷰어의 성향에 따라 철저하게 코딩 컨벤션을 준수하라고 할 수도, 자신의 스타일을 은근슬쩍 강요할 수도, 이도 저도 아니고 알아서 하라고 할 수도 있을 거다.
누군가가 초기에 세팅해둔 툴 덕분에 코드 컨벤션 일부는 강요되므로 준수해나가는 경우도 있을 것이고, 남이야 어떻든 내 코드는 내 스타일대로, 남의 스타일은 맘에 안 들어서, 무시하고 계속 작성해 나갈 수도 있을 것이다. 남의 코드 수준이 자신보다 떨어지는 것 같아, 내 식대로 다 바꿔버리는 경우도 있다. 그러다가 다른 걸 작업하게 되어 작업하던 프로젝트를 다른 사람이 맡아서 또 바꾸고 하다보니, 어느 순간인가 코드 베이스에 여러 스타일이 넘쳐나서 당최 뭐가 어떻게 돌아가는지 알 수가 없는 경우도 생긴다.
이를 테면, 응답값에서 snake case를 쓰고 있었는데 난데없이 camel case를 쓰는 경우도 있었다. 덕분에 호출하는 쪽에서 일괄적으로 응답값을 관리할 수 없어 경우에 맞게 작성하느라 애를 먹기도 하는데, 또 이걸 이어 받아 작업하던 개발자가 이 사정을 제대로 파악하지 못해 수정했다가 버그가 발생하기도 했다.
여러 사람들과 협업하는 것은, 소통 문제도 문제지만, 결국 결과물이 나오는 것도 문제가 많아질 수밖에 없다. 이걸 해결하기 위한 게 표준이다.
가령 우리가 늘상 사용하는 화장실에서 수도꼭지가 표준을 따르지 않는다고 한다면 어떤 일이 생길까? 뭐 기본적인 사용을 할 때는 문제가 되는 줄도 모를 테지만, 어딘가 고장이 나서 고쳐야 하는 상황이 발생하면 문제가 복잡해진다. 맞는 부품을 구하는 것도, 교체하는 방법도, 표준에 벗어나기 때문에 훨씬 더 많은 비용을 지불해야만 한다.
프로그래밍도 마찬가지였다. 정말 상식적이라고 생각하는 부분은 표준을 따를지도 모르겠지만, 실제 작업하는 영역에 들어오면 이 표준이 있냐 없냐에 따라 결과물이 확연히 달라진다.
20년이 넘는 개발을 해오면서 저자가 말하는 실수를 사실 지금도 하고 있다. 안타까운 것은, 어쩌다보니 십수 년째 한 프로젝트를 혼자하는 경우가 너무 많았다는 거다. 그러다보니 이러한 점을 지키는 게 의외로 암묵적으로 진행하고 있었다. 그래서 팀원이 가끔 생길 때마다 이걸 조율하는 게 쉽지가 않았다. 사실 누구나 자신만의 스타일을 갖고 있다보니 자기가 편한대로 개발하고 싶어 했다. 그런 이유로 어느 순간 굉장히 기본적이 굉장히 명확한 부분은 어느 정도 서로 인정하는 표준을 따르게 되는데, 그게 보통은 해당 언어가 보편적으로 따르게 다소 강제하는 부분이라거나, 사용하는 lint 툴의 가이드라인대로 진행하는 거다. 이건 언어 측면의 표준 정도일 뿐이고.
좀더 고차원으로 올라가면, 경험칙만 있다. 몇 년 동안 나보다 고수 개발자들한테 귀동냥으로, 때로는 코드 리뷰를 받으며 깨지고, 또는 작업했던 코드가 버그를 유발해서 그에 대한 반성으로 등 다양한 방면에서 얻은 그 경험칙들이다. 이걸 문자로 남기는 건 제대로 하지 못했는데, 이 책에서 상당히 많이 볼 수 있었다. 아쉬운 점이라면 저자가 비디오 게임 개발자여서, 게다가 C++ 개발자여서, 알려주는 점과 예제 코드가 이해는 되지만, 완전히 와닿지 못하는 점이 있다는 아쉬움은 있다. 하지만 대체적으로는 내가 완전히 수긍하고 또 역으로 배워서 써먹을 점이 많은 부분이 있음을 부정할 순 없다.
제일 와닿는 규칙을 몇 개 나열해보면 아래와 같다.
규칙 01. 최대한 단순하게, 그러나 너무 단순하지 않게 규칙 02. 버그는 전염된다 규칙 03. 좋은 이름은 최고의 문서다 규칙 08. 실행되지 않는 코드는 작동하지 않는다 규칙 13. 산사태를 일으킨 조약돌을 찾으라 규칙 15. 잡초를 뽑으라
그외 규칙은 조금 이해가 되거나 잘 납득할 수 없는 규칙들이다. 틀렸다고 말하고 싶은 게 아니라, 어딘가 나한테는 맞지 않는다거나 공감할만한 경험을 해보지 않은 게 아닐까 싶다.
팀원이 있던 시절, 그 팀원에게 한 얘기가 규칙 01이다. 그 전에 나도 어렴풋이 알고 있었다가 코드 리뷰를 받으면서 리뷰어에게 들은 말이기도 하고, 실제 그렇다는 걸 코드로 증명까지 해봤기 때문에 가장 가치 있는 규칙이다.
내가 리뷰를 하는 날인데, 코드가 무척 장황하게 만들어 왔더랬다. 불필요한 코드도 잔뜩 들어 있고 결론에 이르는 과정이 꽤나 복잡하기도 했던 그런 코드였다. 그래서 간단하게 말한 내용이다.
“코드가 길면 무조건 버그가 있는 겁니다.”
그걸 저렇게 잘 풀어내면 규칙 01. 최대한 단순하게, 그러나 너무 단순하지 않게, 가 된다. 그러면 그 팀원은 어떻게 했을까? 다시 작업해서 딱 필요한 내용만 남기고 정리해 왔다. 결론은? 잘 동작했고, 오히려 단순하게 했기 때문에 코드 상으로만 봐서는 알 수 없는 오류를 잘 파악할 수 있어서 코드 보완이 수월했다. 외부 입력값이 문서나 경험을 벗어나는 값으로 전달 받아서 버그가 발생할 수밖에 없었던 상황이었기 때문이다.
규칙 02. 버그는 전염된다. 이거 부정할 수 있는 사람 있을까? 버그는 무조건 다른 버그를 유발한다. 사용자에게 잘못된 행동을 유발시키든, 화면 처리를 요상하게 하도록 잘못된 코드를 양산시키든, 해당 버그를 가진 코드를 호출해서 내가 잘못된 결론을 내고 엉뚱한 코드를 작성하든, 아무튼 한 번으로는 안 끝는다. 그 여파는 지속되어 최악의 경우 잘못된 데이터를 생성해 DB 데이터까지 요염시킨다. 그러면 그 오염된 데이터 때문에 데이터팀이든, CS팀이든 개발팀 내 다른 팀원이든 그들의 업무를 대폭 늘리게 된다. 그러니 버그는 전염이 맞다.
규칙 03. 좋은 이름은 최고의 문서다. 이걸 부정하는 개발자가 있을까? 일을 하다보면 다소 근시안적인 접근을 하는 개발자, 기획자가 은근 많다. 지금도 변수 이름 하나, 함수 이름 하나 정할 때마다 어려움을 겪곤 한다. 이름 한 번 잘못 정하면 두고두고 그 뜻을 이해하느라 애를 먹는다. 보통은 당장의 그 시점만 고려하는 경우가 많다. 하지만 한 번 쓰고 버릴 코드가 아니라면 이걸 사용하기 시작하는 시점과 이를 중간에 다시 쓰는 시점 등 다양한 시점을 고려해야 하는데, 상상력 부제인 건지, 당장의 문제만 해결하면 된다는 건지, 지금 당장만 통하는 경우만으로 이름을 정한다. 그러면 지금은 의미가 있을지 모르지만, 시간이 지나면 십중팔구 문제를 일으키기 쉽다. 이걸 이해하려면 경험이 쌓여야 하는 것 같다. 아니면 백날 얘기해도 이해하지 못할 게 뻔하니까.
규칙 08. 실행되지 않는 코드는 작동하지 않는다. 와… 이건 뭐 말해 뭐해, 느낌이다. 실행되지 않는 코드를 누가 건드리겠는가? 변화가 있을 때 관련 코드를 건드리고 테스트 하지 않는다면 이건 무조건 문제가 생긴다. 안 쓰는 코드는 버리는 게 맞다. 지금 안 쓰면 나중에도 안 쓸 확률이 매우 높다. 어쩌다가 다시 쓴다? 저자도 git에서 다시 되살리면 되지 않느냐 하는데, 내 경험으로는 그러는 경우는 사실 없다고 봐도 무관할 것 같다. 이걸 되살리는 경우는 지우지 말아야 하는데 지워서 원복하는 경우 말곤 솔직히 못봤다. 삭제됐던 코드가 정상 작동한다고 보장할 수도 없고, 어차피 되살려봐야 이해하고 고쳐야 할 점을 찾는 게 더 비용이 큰 것 같다. 그냥 현재 요구사항에 맞는 내용으로 재작성하는 게 더 빠르더라.
규칙 13. 산사태를 일으킨 조약돌을 찾으라. 지금도 옆에서 그런 모습을 많이 본다. 경력이 많은 이들은 정말 열심히 파고 들어서 증상을 직접적으로 일으키는 점 뿐만 아니라, 이를 유발한 조약돌까지 찾아 근본적인 해결을 하려고 든다. 그런데 대충 경력이 얕거나 경력이 많아도 그렇게까지 하기 귀찮은 사람들은 증상만 해결하고 끝낸다. 그러면 보통은 당장 해당 순간은 넘어가는데 머지 않아 더 큰 문제를 만나 더 큰 비용을 지불하고 해결해야 한다. 그 동안 고객은 회사에 실망하고 이탈하는 데 말이다. 조금만 더 신경쓰면 서로 윈윈했을 텐데 말이다.
규칙 15. 잡초를 뽑으라. 아… 저자는 예제로 주석문 얘기를 했지만, 내가 이 규칙을 읽었을 때 머릿속에 떠오는 건 바로 며칠 전에 회사 동료에게 했던 말이었다. 뭔가를 수정하고 빌드를 진행하고 있었는데, 그 동료가 컴파일이 오래 걸린다고, 레거시 시스템이라 그렇다는 말을 했다. 하지만 나는 그게 왜 그렇게 오래 걸리는 줄 알고 있다. 내가 담당하지 않아서, 당장 다 뒤집을 수 없어서 몇 번 언급만 했었던 것이지만, 역시 일이 커지고 하기 싫은 일이다보니 해결이 안 됐던 부분이었다. 바로 컴파일러가 내뱉는 경고 문구들 때문이었다. 2, 300여 개의 경고문을 출력하느라 컴파일 속도가 느린 것이다. 이걸 한 번 테스트 삼아 정리했고 10개 내외는 정말 없앨 방법이 없어서 남겨뒀었는데, 컴파일 속도가 확연히 달라졌었다. 그래서 이 점을 인지하고 알렸는데, 저자 말처럼 못질하고 싶지 않은 사람이 훨씬 많았던 터였다. 회사 초창기에는 팀장이 경고 무시하지 말고 무조건 해결하라고 했었는데, 지금은… 안타깝다.
공감되는 내용과 더 노력해야 할 내용들을 읽게 되어서 상당히 많은 도움이 되었다. 내가 완전히 공감하지 못하는 부분들에 대해서는 내 나름대로의 방향을 정리하는데 가이드라인으로 사용할 법하다. 내용을 차분히 읽어보면 이야기꾼 면모가 보이는 것 같다. 번역을 깔끔하게, 맛깔나게 잘 하셔서 더 그런 것 같다. 번역투도 아니고, 실제로 저자가 한 말을 잘 이해해서 우리말로 잘 옮겨놓았다. 그래서 품질이 좋다. 그러다보니 저자가 하고자 하는 내용도 잘 이해되는 효과도 있고.
예제 코드를 단발성으로 사용하지 않고, 점진적 개선을 통해 저자가 하고자 하는 내용들을 증명하며 전개해 나가서, 코드를 읽을 수 있는 개발자라면 확실히 도움이 될만한 팁이 많다. 개인적으로는 규칙 19. 평행 재작업 부분이 덜 이해가 되어서, 이 부분을 다시 보면서 파봐야한다. 왜냐하면 이 내용이 현재 내가 겪고 있는 어려움과 직접적으로 연관된 내용이기 때문이다. 낡은 코드, 문제가 되는 코드들을 개선해야 하는데, 건드릴 때마다 문제가 많이 생겨서 애를 많이 먹고 있기 때문이다. 이걸 잘 풀어보면 해결 실마리를 얻을 수 있지 않을까 기대해본다.
뭔가 본인의 개발 틀을 잡고 싶다면 이 책은 강추하고 싶다. 초심자가 이 책에서 얼마나 많은 걸 얻어갈 수 있을진 모르겠지만, 적어도 이런 점이 있다는 걸 인지하고 있으면, 앞으로 개발 업무를 해나갈 때 선임의 말이나 코드를 이해하는 데 많은 도움이 될 거라고 믿는다.
원래 조언처럼 말해주는 건 당시에는 이해하기 어려운 법이다. 내 생각이 너무 강해서 그렇다. 그래서 겪어봐야 아는 것이지만. 결국 이렇게 말할 테니까. “그때 그 말대로 했어야 했는데!”