들어가며
코드를 읽다가 머리가 복잡해지는 경험을 자주 한다. 분명 문법은 알고 있는데 코드가 이해되지 않거나, 한참을 들여다봐도 로직이 머릿속에 들어오지 않는 순간들이 있다. 프로그래머의 뇌를 읽으면서 이런 혼란은 우리 두뇌가 정보를 처리하는 방식과 깊은 관련이 있다는 걸 알게 됐다.
코드를 읽을 때 느끼는 세 가지 혼란
코드를 읽으면서 겪는 어려움을 곰곰이 생각해보니 크게 세 가지로 나눌 수 있었다.
지식의 부족
지식의 부족은 장기 기억 공간, 즉 LTM(Long Term Memory)에 해당 내용이 없을 때 발생한다. LTM은 컴퓨터로 치면 하드 드라이브 같은 건데, 여기에 프로그래밍 언어의 문법이나 알고리즘, 업무 도메인에 대한 지식이 저장돼 있다. 이 지식 자체가 없으면 코드를 이해하기 어렵다.
정보의 부족
정보의 부족은 단기 기억 공간인 STM(Short Term Memory)의 문제다. STM은 캐시나 메인 메모리 같은 개념인데, 여기엔 키워드, 변수명, 자료구조 같은 것들이 임시로 저장된다. STM에는 한 번에 2개에서 6개 사이의 항목만 저장할 수 있다.
연구 결과를 보면 STM에 저장된 정보는 30초를 넘기지 못한다고 한다. 30초가 지나면 장기 기억으로 넘어가거나 그냥 잊혀진다. 그래서 코드를 읽다가 변수명을 까먹거나, 조금 전에 본 함수의 매개변수가 뭐였는지 기억이 안 나는 상황이 자주 발생하는 거다.
처리 능력의 부족
처리 능력의 부족은 작업 기억 공간의 문제인데, 작업 기억 공간은 두뇌의 프로세서 같은 거다. 실제로 사고 작용이 일어나는 곳이다. 머릿속으로 코드를 실행해보면서 이해하려고 할 때, 인지적으로 복잡한 작업을 할 때 이 공간을 사용한다.
두뇌가 생각하고 새로운 아이디어를 형성하고 문제를 해결하는 능력 자체가 이 작업 기억 공간의 용량에 달려 있다. 코드의 복잡도가 높으면 두뇌의 처리 용량이 부족해져서 혼란을 느끼게 된다.
기억 용량 제한 극복
생소한 코드를 읽기 어려운 이유를 따져보면 결국 STM의 용량 제한 때문이다. 우리 두뇌에는 이 한계를 극복하는 방법이 있다. 바로 청킹이라는 방법이다. 기억 용량의 경우 LTM이 STM보다 훨씬 크다. 그래서 새로운 정보를 기억할 때 STM은 LTM과 협업한다. 새로운 정보를 읽을 때 두뇌는 정보를 청크라는 몇 개의 묶음으로 나눈다.
청킹의 원리
LTM에 지식이 부족하면 하위 수준의 정보들, 그러니까 문자 하나하나, 키워드 하나하나 같은 것들에 의존해야 하는데 그러면 STM이 빠르게 소진된다. 반대로 LTM에 지식이 많으면 기억을 훨씬 쉽게 할 수 있다. 예를 들어 LTM에 지식이 많은 경우, 코드의 하위 요소들을 STM에 일일이 저장하는 대신 ‘자바에서의 for 루프’처럼 추상 개념으로 기억할 수 있다. 그러면 STM을 훨씬 절약할 수 있다.
이걸 쉽게 설명하는 예시가 있다. cat loves cake와 abk mrtpi gbar를 비교해보면, 전자는 LTM에 cat, loves, cake라는 단어가 이미 있기 때문에 STM에 저장할 게 많지 않다. 그냥 세 개의 단어로 기억하면 된다. 하지만 후자는 의미를 모르는 문자열이라서 각 알파벳을 다 기억해야 한다. 이렇게 청크는 몇 개의 그룹으로 묶은 정보로써 기억 공간 하나만 차지한다.
청킹의 실제 효과
연구 결과에 따르면 코드를 숙련된 프로그래머, 중급자, 초보자에게 보여줬더니 예상대로 숙련된 프로그래머가 가장 잘 기억했다. 그런데 코드 줄을 무작위로 섞어서 보여줬을 때는 세 그룹 간의 차이가 거의 없었다. 숙련된 프로그래머들은 코드의 구조와 패턴을 인식해서 청킹하고 있다는 거다. 코드가 무작위로 섞이면 그런 패턴이 사라지니까 청킹의 이점도 사라진 거다.
코드를 읽을 때 우선 영상 기억 공간에 저장되지만 아주 적은 일부만이 STM으로 보내진다. 그래서 디자인 패턴에 대한 지식을 가지고 있으면 청킹 능력이 향상되고 코드를 빠르게 수정할 수 있다. 주석도 청킹 작업에 도움을 준다. 코드를 일일이 세세하게 설명하는 주석이 아닌 적절한 수준의 주석을 말하는 거다.
코드와 청킹
쉽게 기억할 수 있는 코드는 내가 이미 잘 알고 있는 디자인 패턴이나 프로그래밍 구성 요소, 도메인 지식을 드러내는 코드다. 그래서 이런 코드는 지식 자가 진단 도구로도 사용될 수 있다. 내가 어떤 코드를 쉽게 기억한다면, 그건 내가 그 분야의 지식을 잘 갖추고 있다는 뜻이다. 결국 코드는 우리 두뇌에서 처리하기 쉽게 만드는 특징들을 가질 수 있다. 디자인 패턴이나 주석문, 명확한 표식 같은 것들 말이다.
프로그래밍 문법을 빠르게 배우는 방법
의도적으로 기억하기
메서드 같은 것들은 쉽게 검색해서 찾아 볼 수 있기 때문에 열심히 외우려고 하지는 않는다. 하지만 알고 있다면 코드를 파악하기가 훨씬 수월해진다. 앞서 본 것처럼 두뇌는 관련 지식을 더 많이 알수록 코드를 쉽게 분리하고, 기억하고, 처리할 수 있다.
업무 도중 검색을 함으로써 흐름이 끊기게 되면 생산성에 큰 영향을 미친다. 왜냐하면 코드와 관련한 중요한 정보를 잊어버리기 때문이다. 검색한다는 것 자체가 그 내용에 대해 아직 모른다는 뜻이다. 그래서 검색하기 전에 의도적으로 기억하려고 시도하는 게 좋다. 노력 그 자체가 기억을 강화한다. 읽고 듣고 보고 난 후 STM에 저장된 정보가 LTM으로 옮겨지긴 하지만, 그냥 옮겨진 정보는 오래 저장되지 않는다.
오래 기억하는 방법
두뇌의 기억은 네트워크 구조로 되어 있다. 하나의 사실은 다른 많은 사실과 연결되어 있다. 그래서 새로운 정보를 배울 때 기존의 지식과 연결시키는 게 중요하다. 오랫동안 학습한 만큼 오래 기억한다는 말이 있는데, 여기서 오랫동안이라는 건 많은 시간을 한 번에 쏟아붓는 게 아니라 오랜 간격을 두고 학습해야 한다는 뜻이다.
저장 강도와 인출 강도
반복은 기억을 강화시킨다. 특히 긴 간격을 두고 반복하면 LTM에 영구적으로 남는다. 기억에는 두 가지 강도가 있는데, 저장 강도와 인출 강도다.
저장 강도는 감소하지 않고 계속 늘어나지만, 인출 강도는 시간이 흐를수록 약해진다. 반복 학습은 저장 강도를 강화시킨다. 그리고 이미 알고 있다고 생각하는 내용을 기억하려고 노력하면 추가 학습 없이도 인출 강도가 강화된다. 그래서 검색하기 전에 먼저 기억해내려고 시도하는 게 중요한 거다.
정교화
정교화라는 개념도 있다. 정보에 대해 능동적으로 생각하고 반추하는 과정을 말한다. 복잡한 프로그래밍 개념을 학습할 때 이 방법이 특히 효과가 좋다. 그냥 수동적으로 읽기만 하는 게 아니라, 그 정보에 대해 능동적으로 생각하고, 기존 지식과 연결시키고, 예시를 만들어보고, 다른 개념과 비교해보는 거다.
인지 부하
STM이 2개에서 6개의 항목만 기억할 수 있다는 걸 얘기했는데, 작업 기억 공간의 맥락에서 이 용량을 인지 부하라고 부른다. 인지 부하에는 두 가지 종류가 있다. 내재적 부하와 외재적 인지 부하다.
내재적 부하와 외재적 인지 부하
내재적 부하는 문제 자체가 갖는 특성 때문에 발생한다. 예를 들어 문제를 풀기 위한 다른 방법 없이 정해진 공식만이 존재할 때 발생하는 인지 부하다. 이건 문제의 본질적인 복잡성이라서 줄이기 어렵다.
외재적 인지 부하는 내재적 부하에 추가로 발생하는 인지 부하다. 예를 들어 숫자를 변수화 했을 때 발생하는 추가적인 인지 작업 같은 거다. 다만 특정 개념을 많이 경험할수록 외재적 인지 부하는 적어진다. 처음엔 변수명을 추적하는 게 어렵지만, 익숙해지면 자연스러워지는 것처럼 말이다.
인지 부하를 줄이는 방법
인지 부하를 줄이는 방법으로 리팩터링이 있다. 리팩터링은 기능은 유지하면서 내부 구조를 개선하는 거다. 보통은 장기적으로 가독성이 높고 유지보수하기 좋은 코드로 만드는 걸 목표로 하는데, 여기서 중요한 건 현시점에서 개발자가 읽기 쉬운 코드로 변경하는 거다. 단순히 먼 미래의 유지보수를 위한 게 아니라, 지금 당장 코드를 이해하기 쉽게 만드는 거다.
예를 들어 메서드 호출부와 정의를 가까이 두는 것만으로도 인지 부하를 줄일 수 있다. 메서드를 추적하기 위해 파일을 위아래로 스크롤하는 수고를 덜 수 있으니까.
의존 그래프를 생성하는 것도 도움이 된다. 코드를 바탕으로 의존 그래프를 그려보면 흐름을 이해하고 논리적 흐름에 따라 코드를 읽는 데 도움이 된다. 특히 복잡하고 서로 밀접하게 연결되어 있는 코드를 이해할 때 의존 그래프는 정말 유용하다. 어떤 함수가 어떤 함수를 호출하는지, 데이터가 어떻게 흐르는지 시각화하면 머릿속에서 코드의 구조가 훨씬 명확해진다.
정리하면서
이렇게 정리해보니 코드를 읽는 건 단순히 텍스트를 보는 게 아니라 우리 두뇌의 여러 기억 시스템을 총동원하는 복잡한 인지 활동이라는 걸 새삼 깨닫는다.
결국 좋은 코드란 컴퓨터가 실행하기 좋은 코드가 아니라, 사람이 읽고 이해하기 쉬운 코드인 것 같다. 내 두뇌가 어떻게 작동하는지 이해하고, 그에 맞춰 코드를 작성하고 읽는다면 더 나은 프로그래머가 될 수 있을 것 같다.