본문 바로가기
카이스트 정글

야크셰이빙 중독

by hjy00n 2024. 9. 21.

출처: https://sketchplanations.com/yak-shaving

 

야크셰이빙(Yak shaving)이라는 용어를 그대로 해석하면 "야크 털 깎기" 지만, 아래와 같은 의미로 쓰인다.

본래의 목적을 이루는데에 필수적이지 않은 부수적인 작업들을 하다 결국 전혀 다른 일을 하고 있는 모습

 

예시를 들면 다음과 같다.

  1. 봄이 왔으니 세차를 해야겠네
  2. 이런, 호스가 망가졌네. 홈 디포우에서 새 호스를 사야겠어
  3. 하지만 홈 디포우는 Tappan Zee 다리를 건너편에 있어. 톨게이트를 지나기 위해 EzPass가 필요하네
  4. 옆 집에 사는 Bob에게 EzPass를 빌려야겠어
  5. 그런데 아들이 Bob한테서 보이스카웃에 가려고 베개를 빌려갔었는데...
  6. Bob에게 빌려간 베개를 돌려주기 전까지는 EzPass를 빌려주지 않을 거야
  7. 베개의 야크 털이 많이 빠져서 지금 당장 돌려줄 수 없겠어
  8. 베개에 넣을 야크 털을 구해서 채워야겠어
  9. 결국, 세차를 하기 위해 동물원에 가서 야크 털을 깎기 시작한다

좀 뜬금없지만, 지금 이 글을 쓴 것도 결국 야크셰이빙이라 할 수 있겠다.

 

나는 야크셰이빙 중독자다. 특히 컴퓨터와 관련된 것이라면 더욱 그렇다. 실제로 코딩이나 개발, 이론 공부를 할때면 항상 어떠한 의문이 생기기 마련인데, 그 의문을 해결하기 위해 본래의 목적과는 다르게 옆길로 새는 경우가 매우 흔하다. 그럼에도 불구하고 다행인 것은, 결국 돌고 돌아 본래의 목적을 어떻게든 달성한다는 점이다. 물론 그 과정이 매우 험난하고 정신을 차리고 보면 시간이 훌쩍 지나가있다. 이렇게 야크셰이빙을 위해 부수적인 일들을 한 사이클 돌고나면 컴퓨터에 대한 전반적인 지식들을 알게되고, 결국 언젠가 그 지식을 활용할 수 있는 타이밍이 온다. 결국 그러한 지식들이 새로운 지식을 습득하는데에 가속도를 붙여주는 것이다. 이러한 야크셰이빙을 할 때, 그리고 돌고 돌아 결국 문제를 해결할때 나는 전율을 느낀다.

 

예를 들면 아래와 같다.

 

백준 알고리즘을 풀다가, 맞왜틀(맞았는 데 왜 틀렸지?)을 결국 해결하지 못하다가, 결국 반례찾는 코드를 직접 작성한 적도 있다. 원리는 간단하다. 우선 정답 코드를 구하고, 랜덤한 입력 케이스를 만든 뒤, 정답 코드와 내 코드에 입력 케이스를 주고, 출력이 다른 케이스를 찾는 것이다. 그 케이스가 반례가 된다.

 

또한, 문제를 풀때, 여러가지 입력 케이스들을 테스트 해보고 싶을 수 있다. 이때마다 매번 입력 케이스를 직접 복붙을 하는 것이 불편해서 이것을 자동으로 할 수 있는 스크립트도 작성한 적이 있다. 마찬가지로 간단하다. 특정한 패턴의 파일명으로 입력 케이스를 만들어 놓고, 스크립트를 실행하면 자동으로 정해진 파일에 해당 입력케이스를 주는 방식이다.

 

이러한 의문점도 있었다.

 

항상 백준에서 파이썬으로 문제를 풀때, 코드를 함수로 감싸고, 그 함수를 실행하는 것이 속도가 더 빠르다는 것이다. 이것도 결국 의문이 풀렸다. 요약하자면, 지역변수와 전역변수가 CPython의 바이트 코드로 변환될 때 다르게 변환된다는 점이다. 상세한 내용은 링크를 잠조하길 바란다.

 

정글 0주차땐 다음과 같은 고민도 했었다.

 

python의 flask 프레임워크 사용 시, flask 명령어로 app 서버를 띄울 수 있다. 그렇다면 gunicorn의 역할을 이미 하고 있는게 아닌가? flask에서 socketio를 사용해 채팅 기능을 구현했는데, 왜 gunicorn의 worker class를 gevent로 해야 의도한대로 작동하는가? gunicorn없이 nginx만 사용하면 안되는가? gunicorn대신 uvicorn을 사용하면 안되는가?

 

이러한 과정에서 flask 내장 웹서버의 한계점, python의 GIL 개념, python에서 동시성을 처리하는 방법, gunicorn, nginx, flask app server 차이점 등등 이해할 수 있게 된다.

 

더 나아가서 nginx와 https에 대해서 아키텍쳐를 설계하던 중, SSL 인증서 관리에 관한 고민도 해보고, certbot 자동화 스크립트도 구현해보았다.

 

2주차 알고리즘땐 아래와 같은 의문점이 있었다.

 

Disjoint Set 파트의 Union-Find 및 Find 연산에 관한 내용이었다. union by rank 와 path compression 기법을 사용해서 좀 더 시간 복잡도를 줄일 수 있다. 여기서 의문점은 rank 가 트리의 최대 height 였던 값을 저장하고, 그 이후로 path compression 을 통해 실제 height가 감소함에도 여전히 계속 유지되는 rank 값을 이용해서 어느 트리에서 어느 트리로 합쳐질지 연산한다. 이 부분이 좀 혼란스웠다. 그러나 알고보니 rank 기법은 정확한 값이 아닌 휴리스틱 하게 사용되는 기법이었다. (그러나 시간 복잡도가 감소하는 증명은 존재함)

 

또, 4주차인 rbtree를 할 때는, 다음과 같은 의문점이 있었다.

 

Sentinel node가 필요한 이유는 무엇일까? 이론상으로, 그리고 경험적으로 충분히 판단할 수 있었지만, 직접 느껴보고 싶었기 때문에 Sentinel node를 사용하지 않고 구현해 보았다. 결국 NULL을 만나면 부모노드를 역추적할 수 없기 때문에, 그리고 코드의 일관성을 지킬 수 있기 때문이라는 것을 새삼 깨달을 수 있었다.

 

5주차인 malloc-lab 때는, 다음과 같은 의문점이 있었다.

 

왜 gdb로도 정확히 에러가 발생하는 지점을 찾을 수 없는것일까? bt로도 스택트레이스 제대로 추적하지 못하는 이유는 무엇을까? 내가 아직 모르는 gdb 기능이 있는가? 컴파일 옵션에 문제가 있는가? 내가 무엇을 놓치고 있나?

 

6주차인 현재, proxy-lab 에서는 다음과 같은 의문점이 있었다.

 

같은 코드인데 왜 os 환경에 따라 다른 결과가 나올까? 왜 프로세스를 이용한 동시성 모델이 왜 싱글 프로세스 단순 반복 모델보다 느린 이유가 무엇일까? 이것을 검증하기 위해 실제로 간단한 동시 요청 스크립트를 작성해서 테스트를 해보았다.

 

정말 크게 돌고돌아 문제를 해결한 적도 있다. 그 때의 야크셰이빙은 "리눅스 설치" 였다. 윈도우 환경에서 개발을 할 때, WSL을 사용했었는데 이때 한계점을 느꼈던 것이 이유였다.

 

리눅스 설치는 그 자체만으로 챌린지다. 물론 어떤 배포판이냐에 따라 다르겠지만, 첫 리눅스를 Ubuntu가 아닌, Arch나 Gentoo, 심지어 LFS(Linux From Scratch)를 선택한다면 헬게이트가 열릴 것이다. 목표를 "리눅스 설치"로 다시 설정하고, 그에 따른 새로운 야크셰이빙들이 생겨날 것이다. 그렇게 되면 또 다시 엄청난 시간을 쓰게 될 것이고, 리눅스 시스템에 대한 이해가 상당해질 것이다. 왜 리눅스가 개발에 유리한지, 왜 리눅스가 서버로 선호되는지, 그리고 자동화, 네트워크, 커맨드라인, vim, emacs, 등등 잡다한 지식에 매료될 것은 물론이고, 마우스보단 키보드를 선호하게 될 것이며, 결국 HHKB(Happy Hacking Keyboard)를 사용하게 될 것이다. 당신은 깨달음을 얻는 것과 동시에 Linux의 늪에서 빠져나오지 못할 것이다.

 

하지만 여전히 풀리지 않은 의문점도 많다. 다양한 이슈들을 경험해보고, 또 다양한 방법으로의 접근을 통해 문제해결 능력을 키울 수 있다.

 

그러나 양날의 검이기도 하다.

 

야크셰이빙은 시간적 여유가 있을때 가장 효과적이다. 먄약, 마감기한이 임박한 작업을 할 때는, 작업 속도에 좀 더 집중해야 한다.

 

또한, 야크셰이빙은 지극히 개개인의 의문점, 의식의 흐름에 따라 문제 해결의 중요도 및 순서가 달라진다. 함께 스터디를 하는 상황에서는 개개인의 학습 페이스가 다를 수 있다. 누군가는 특정 부분에 대해 좀 더 깊은 이해를 원할 수 도 있고, 또다른 의문점이 생길 수도 있으며, 잠시 다른 개념에 대해 먼저 선행학습을 하고 싶어질 수도 있다. 나의 경우에도 이런 경우를 많이 겪었다. 의문이 해결되지 않은채로 찝찝함이 남아 있다거나, 잠시 곰곰히 생각해보는 시간을 가지고 싶었으나 그러지 못하거나, 내 의식의 흐름이 아닌, 옆사람의 의식의 흐름에 강제로 흘러가는 경우가 그렇다.

 

이 부분에 대해서는 여전히 딜레마로 남아있다. 아마도 상황에 따른 밸런스가 중요할 것이라 생각하지만, 과연 황금비는 무엇일까 항상 고민한다.


P.S.

우리가 거의 매일같이 쓰는 유명한 프로그램인 git도 사실 야크셰이빙의 일종이라 할 수 있다. git은 리누스 토르발즈가 만들었는데 개발 비화는 링크를 참조.

 

 

 

'카이스트 정글' 카테고리의 다른 글

pintos project1: threads  (0) 2024.10.01
Proxy Lab 그리고 ECF  (0) 2024.09.25
Malloc Lab 그리고 CS:APP  (0) 2024.09.13
레드-블랙 트리 그리고 C언어  (0) 2024.09.12
정글 나인 헬퍼 제작 후기  (0) 2024.09.06