프로필 사진
운체조교
bolt icon4.4k·5개월·
6.1k
공유

삽질도 많이 해봐야 잘 한다

기본기는 중요합니다. 그 중, 어디서도 배울 수 없는 기본기가 “삽질”입니다. 말그대로 노가다에 가까운 짓들인데, 이것들이 시간 낭비가 아니라 본질에 가까운 고민을 하기 위한 준비 과정임을 케이스마다 설명 드립니다.


1. 구글링


익숙한 입장에서는 왜 얘기를 하나 싶으실텐데, 익숙하지 않은 입장에서는 구글링도 훈련이 필요한 영역입니다.


어떤 근거는 믿어도 되는지, 어떤 검색 결과는 사례로서만 생각해야 하는지 등등... 상사에게 "이게 뭔가요" 라고 물어봅할 것들 중 95%는 구글링으로 해결할 수 있습니다.


꼭 검색할 때는 영어로 하시면 좋겠고, 양질의 정보와 그렇지 않은 정보를 구분하는 능력을 몸으로 부딪히면서 익히셨으면 좋겠습니다.


2. 오픈소스 코드 읽기


구글링으로 안되는건 무조건 나옵니다. 이 5%에 해당하는 문제는 직접 소스코드를 읽으셔야 합니다. 믿기지 않는 소리로 느껴지실 수 있는데 (전 개인적으로 믿고 싶지 않았습니다...) 현실입니다. 제대로된 프로덕트를 만드시려면 기반 오픈소스를 다 읽으셔야 하거나, 최소한 읽으실 준비가 되셔야 합니다.


System.out.println() 함수가 어떻게 작동하시는지 궁금하시다면, Ctrl + 클릭으로 println() 함수를 누르고 쭉 파고 들어가 보세요. 처음부터 되진 않겠지만 계속 하다보면 어느 순간 내 코드가 돌아가면 지금 CPU에서 무슨 일이 일어나는지까지 이해하실 수 있습니다. (최소한 어디까지는 알고 어디까지는 모를 수 밖에 없는지 아실 수 있을겁니다)


MySQL에 select * from table; 을 던졌을 때 무슨 일이 일어나는지 궁금하면 코드를 읽으면 됩니다. 빡센데, 절대 불가능하지 않습니다.


3. 컴파일


읽었다면 수정해보고 돌려봐야겠죠. 이를 위해서는 컴파일이 필요합니다.


Spring framework 컴파일 해보셨나요? (설정이 아닙니다) OpenJDK는요? Eclipse? IntelliJ?

생각보다 컴파일, 빡셉니다. 의존성 하나하나 고려하면서 제대로 컴파일하는 것이 이미 해본 사람 입장에서는 그냥 일상으로 하는 것인데, 안해본 사람은 Spring이 컴파일이 가능하다는 상상이 어려울 수도 있습니다.

네, 여러분이 쓰는 모든 오픈소스 프로젝트는 컴파일이 됩니다. 컴파일 한번 해보세요. 귀찮은 과정이라고 여겨져서 중간에 포기할 수 있는데, 사실은 이거 어렵고, 이 어려운 과정을 개선하는건 오픈소스 커뮤니티 입장에서도 감사한 기여일 수 있습니다. 한번쯤은 필요한 삽질입니다.


4. (규모가 적당하다는 전제 하에) 모든 메모리 할당 혹은 참조를 직접 카운팅 해보세요.


위에까지는 기반 코드를 읽는 일이라면 이젠 내가 짠 코드들에 대한 얘기입니다. 메모리 할당와 그 할당된 영역에 대한 참조를 모두 트래킹 해보세요.

이딴 노가다를 왜 시키나, 싶으실텐데 실제로 오래 돌려야 하는 프로그램 중에 메모리 터져서 죽는 경우는 그냥 노가다로 참조 트래킹해서 실수로 들고 있나를 따져 보는 수 밖에 없습니다.


이게 규모가 커진 후에 하면 빡세니까, 저는 코드 짤 때 미리 할당의 life cycle을 체크하려고 노력합니다. 혹은 Rust 같은 언어는 컴파일 타임에 이런 차원의 문제를 해결해 주기 위한 많은 기능을 포함하고 있습니다.


5. (역시 가능한 범위 내에서) 내가 짠 코드가 line by line으로 어떻게 실행되는지를 살펴보세요.


매우 중요한데, 당연히 내가 짠 언어의 문법에 따라 한줄 한줄 돌아가는 것도 알아야 겠지만, 진짜 필요한건 컴파일 된 이후에 어셈블리 단에서 한줄 한줄이 어떻게 가나를 볼 줄 알아야 합니다. C/C++ 과 같이 네이티브 언어가 아니면 어려울 수 있지만 (그래서 전 절대 안터져야 하는 경우, mission critical 하다고 하죠, 는 타 언어로 짜는걸 별로 선호하지 않습니다. 생산성이고 뭐고 내가 책임질 수 있는 범위가 정해지지 않으니...) 필요없는 것이 아닙니다.


실제로 제가 인턴한 N사의 경우, jvm 파라미터 튜닝 할 줄 아는 엔지니어가 많았고, 사내 스터디에서도 자바 엔지니어들이 앉아서 OpenJDK C++ 코드 보면서 할당 전략 공부하고 그랬습니다.


이게 진짜 중요해 지는게 멀티 쓰레딩이나 멀티 프로세싱을 할 때입니다. 아무리 앱단을 짜도 성능이 느려지거나, 예상처럼 scale out이 안되면 문제가 런타임이나 어셈 단에서 발생 하는 경우가 없지 않습니다.


다른 경우는 알고리즘 성능 평가할 때 인데, the art of computer programming 같은 알고리즘 고전이 어셈으로 짜여진 이유가 있습니다. 진짜 성능 평가를 하려면 연산의 횟수를 세야 하는데, 고급 프로그래밍 언어에서는 연산 횟수 세는게 어렵습니다. 어셈은 jmp만 따라갈 줄 알면 그냥 그 루프 안에서 연산자 개수를 세면 됩니다.


6. 결론


위에 언급한 고전인 The Art of Computer Programming을 쓴 Donald Knuth 교수는 "알고리즘을 이해하는 방법은 테이블 옆에 써놓고 코드 한줄 실행될 때 다음에 값이 어떻게 바뀌는지를 적어보는 수 밖에 없다" 고 얘기했습니다.


솔직히 예전에는, 개소리라고 생각했습니다 (...) 언제 저걸 다 하고 앉아 있냐고요. 알고리즘 시간 복잡도 외우기도 빡센데...


최근엔 동감합니다. 전문가라는 사람들은 책임을 져야 하는 사람들이고, 프로페셔널 프로그래머는 자신의 코드 한줄 한줄에 모두 책임을 져야 합니다. 이 책임의 "해상도"에 그 프로그래머의 가치가 매겨진다는 생각을 합니다. 책임감 없이 추상화한 코드로 생산성을 올리는 것은 누구나 할 수 있지만, 저 해상도를 아는 상태로 원래 의미를 훼손하지 않는 추상 계층을 만드는 것은 실력이 있어야 합니다.


또한 추상 계층의 설계는 명확한 전제와 방향성이 있어야 합니다. 제가 생각하는 이상적인 추상은 원래 의미는 바꾸지 않으면서 더 나은 논의를 가능케 해야 합니다. 마치 진공관이 트랜지스터로 바뀐 후 논리 게이트를 만들 수 있었고, 더이상 컴퓨터가 전자공학의 영역이 아닌 논리 회로의 영역이 된 것과 마찬가지입니다.


다시 코드로 돌아오면, 모든 코드를 다 높은 해상도로 봐야 하는건 아닙니다. 데드라인을 맞추기 위한 생산성 있는 프로젝트 수행 능력도 필요하고, 추상화도 필요합니다. 요새는 커뮤니케이션 능력과 기획력도 필요합니다. 다만 프로페셔널 프로그래머는 "만번에 한번 발생하는", 0.01% 정도 발생하는 예외 상황을 예측 가능한 시간 안에 해결할 줄 알아야 하고, 그걸 위해 제가 말한 저 삽질들을 잘하는 것은 매우 필요한 일입니다.


위에 써놓은걸 당장 다 알아야 한다는 얘기가 아님을 거듭 강조합니다. 언젠간 저 방향으로 가도록 공부를 해야 합니다. 그래서 기초가 중요하다는 말을 하고 싶었습니다.


좋은 하루 되시길!

43
cat-footer