들어가며
코드를 작성할 때 코드를 검색하고, 이해하고, 작성하고, 수정하고, 탐구하면서 복잡한 인지 활동을 한다. 각각의 활동은 두뇌의 서로 다른 기억 시스템에 부담을 준다. 프로그래머의 뇌의 코딩에서의 협업 파트를 읽고 코딩이라는 행위를 인지과학의 관점에서 분해해보고, 어떻게 하면 더 효과적으로 일할 수 있을지에 관한 내용을 알 수 있었다.
코드를 작성하는 다섯 가지 활동
검색: 코드베이스를 헤매는 시간 버그의 정확한 위치를 찾거나, 특정 메서드가 어디서 호출되는지 추적하거나, 변수가 초기화되는 위치를 찾는 활동이 검색이다. 이 과정은 STM에 무리를 준다. 검색 대상, 지금까지 탐색한 경로와 이유, 다음에 살펴봐야 할 사항까지 머릿속에 담아두려면 STM이 빠르게 소진된다.
그래서 별도로 메모하면 도움이 된다. 또 특정 작업을 쉽게 하기 위해 코드를 일시적으로 변경하는 것도 유익하다. 예를 들어 “여기까지 확인했고 다음은 이 부분”처럼 주석문으로 작성해놓으면, 나중에 다시 돌아왔을 때 빠르게 맥락을 파악할 수 있다.
이해: 코드를 읽는 시간 작성된 지 오래됐거나 다른 사람이 작성한 코드의 기능을 이해하는 활동이다. 연구 결과에 따르면 소스 코드를 이해하는 시간은 최대 60%나 된다고 한다. 생각보다 엄청나게 많은 시간이다.
이해 활동은 작업 기억 공간에 부담을 준다. 코드에 대한 모델을 만들고, 새로운 정보를 읽을 때마다 모델을 갱신해야 하기 때문이다. 뇌에서 정보를 계속 인출하는 대신, 외부 소스에 메모를 남기거나 다이어그램을 그려두면 정보를 훨씬 용이하게 검색할 수 있다.
전사: 계획을 코드로 옮기기 구체적인 계획이 있고 그걸 코드로 옮기는 활동이 전사다. 단순히 코딩하는 활동처럼 보이지만, 구현을 위해 문법 구조를 떠올려야 해서 LTM에 부하를 준다. 문법을 잘 알고 있으면 LTM에 가는 부담이 적지만, 생소한 언어라면 계속 막히게 된다.
증가: 모든 게 합쳐진 복잡한 활동 검색, 이해, 전사가 합쳐진 활동이 증가다. 코드를 추가할 위치를 검색하고, 기존 코드를 파악해서 이해하고, 아이디어를 실제 문법으로 전사하는 활동이 모두 포함된다.
세 가지 기억 체계에 모두 부하를 주기 때문에 가장 힘든 활동 중 하나다. 어느 기억 공간이 영향을 많이 받을지는 개인적 경험에 따라 달라진다. 문법을 잘 알면 LTM에 가는 영향이 적고, 코드베이스를 잘 안다면 이해할 때 작업 기억 공간과 STM에 가하는 부하가 크지 않다.
코드베이스나 언어가 생소하면 작업이 정말 어렵다. 증가 작업을 여러 개로 분할하면 좋다. 하위 작업을 신중하게 수행하여 기억 체계를 지원할 수 있다.
탐구: 코드로 스케치하기 무엇을 해야 할지 분명한 생각이 떠오르지 않을 때, 프로그래밍을 통해 문제의 도메인과 사용해야 하는 프로그래밍 구성 요소를 명확히 알아가는 과정이 탐구다.
코드 작성, 코드 실행, 테스트 실행, 기존 코드 읽기 등 여러 가지 프로그래밍 관련 작업을 연속적으로 수행한다. 세 가지 기억 공간 모두 어려움을 겪는다. 계획과 디자인을 즉석에서 하기 때문에 작업 기억 공간에 특히 의존한다.
계획을 문서화하면 일하는 흐름이 흐트러지고 속도가 느려진다고 느낄 수 있다. 하지만 설계의 방향이나 결정 사항을 대략 적어두면 문제를 더 깊이 생각할 수 있는 마음의 여유가 확보된다.
프로그래머의 업무 중단
중단의 비용
개발자의 업무 시간의 20%가 업무 중단에 쓰인다는 연구 결과가 있다. 업무 중단이 일어나면 작업 기억 공간이 원래 작업하던 코드에 대한 중요한 정보를 잃어버리기 때문에 생산성에 악영향을 미치게 된다. 업무 중단의 비용이 크지 않다 생각을 했었는데, 생각보다 미치는 영향이 컸다.
중단에 대비하는 방법
정신 모델 저장하기
메모, 모델에 대한 그림 등의 작업도 중단으로부터 복구하는 데 유용할 수 있다.
주석을 남기면 지금 내가 무엇을 하고 있는지, 왜 이 코드를 보고 있는지 간단하게라도 적어두면 나중에 돌아왔을 때 훨씬 빠르게 작업을 재개할 수 있다.
미래 기억 향상하기
미래에 무언가를 할 것인가에 대한 기억을 미래 기억이라고 한다. 계획 및 문제 해결과 관련이 있다. “이 부분 리팩터링 필요”, “여기 테스트 추가해야 함” 같은 TODO를 명시적으로 기록해두면 좋다.
하위 목표 라벨 붙이기
문제를 어떤 작은 단계로 나눌 수 있는지 명시적으로 기록해두면 좋다. 업무가 중단되고 나서 다시 코드로 돌아가서 무엇을 하려고 했는지 기억할 때 도움을 받을 수 있다. 이를 통해 코드의 작은 부분을 채울 수 있고 실패 시 대처할 계획을 세워둘 수도 있다.
대규모 시스템의 설계와 개선
코드베이스의 특성 또한 작업자가 코드베이스와 상호작용하는 방식에 큰 영향을 미친다. 예를 들어 코드베이스의 점도가 높은 경우 코드베이스에서 작업하는 미래의 개발자는 변경을 꺼릴 수 있다. 이로 인해 코드베이스 구조가 크게 변경되기보다는 패치가 더해져서 코드가 점점 복잡해진다.
만약 오픈 소스 코드베이스가 힘든 정신 활동을 필요로 한다면, 코드가 유지보수될 가능성은 더 낮다. 코드베이스가 여러 다양한 차원에서 어떻게 작동하는지 파악하는 것이 중요하다.
코드베이스의 인지 차원
CDN은 인지적 관점에서 코드베이스를 조사하는 기술이다. 대규모 코드베이스에 대해 사람들이 코드를 쉽게 변경할 수 있는지, 정보를 쉽게 찾을 수 있는지와 같은 질문에 답을 찾는 데 도움이 된다.
주요 차원들을 살펴보면 다음과 같다.
-
오류 경향성: 일부 언어는 다른 언어보다 실수를 저지르기 쉽다. 일관성 없는 규칙, 문서 부족, 모호한 이름이 오류 경향성을 가진다.
-
일관성: 일관성 없는 이름과 규약은 인지 부하를 많이 가져온다. 두뇌가 무엇에 대한 것인지 이해하는 데 더 많은 에너지를 소모하고, 관련 정보를 찾는 데 더 많은 시간을 쓴다.
-
분산성: 프로그래밍 구성 요소가 얼마나 많은 공간을 차지하는지를 나타낸다. 분산성은 코드의 줄 수만이 아니라 코드가 얼마나 많은 청크로 구성되어 있는지도 고려할 수 있다.
-
숨겨진 의존성: 의존 항목이 사용자에게 어느 정도로 가시적으로 나타나는지를 말한다. HTML 페이지에 자바스크립트로 제어되는 버튼이 있고 자바스크립트는 다른 파일에 저장되어 있는 경우, 함수가 어느 HTML 페이지로부터 호출되는지 알기 어렵다. 이게 숨겨진 의존성이다.
-
잠정성: 도구를 사용하는 동안 생각하는 것이 얼마나 쉬운지를 나타낸다. 코드베이스나 프로그래밍 언어가 매우 엄격하면 코드를 사용해 생각을 표현하는 것이 어렵다. 잠정성이 낮은 경우다.
-
점도: 특정 시스템을 변경하는 것이 얼마나 어려운가에 대한 차원이다. 잠정성과 관련 있다.
-
점진적 평가: 주어진 시스템에서 부분적인 작업을 확인하거나 실행하는 것이 얼마나 쉬운지를 말한다.
-
역할 표현력: 프로그램에서 여러 가지 다른 부분의 역할을 얼마나 쉽게 알 수 있는지를 나타낸다.
-
매핑 접근성: 프로그래밍 언어 또는 코드가 문제의 해결 영역에 얼마나 가까운지를 의미한다.
-
힘든 정신 활동: 어떤 시스템에서는 사용자가 시스템의 외부에서 힘든 정신 활동을 수행할 때 생각하는 것이 매우 어렵다. 주로 작업자가 기억해야 할 것이 많은 상황이다.
-
보조 표기법: 프로그래머가 공식 규격에는 없는 의미를 코드에 추가할 가능성을 말한다. 소스코드에 주석문을 추가할 가능성 같은 거다.
-
추상화: 시스템의 사용자가 기본적으로 제공되는 추상화만큼 강력한 추상화를 만들 수 있는지 여부다. 함수, 객체, 클래스를 만드는 것을 예로 들 수 있다. 사용자가 함수를 만들 수 있다는 사실은 사용자가 자신만의 구성 요소로 언어를 형성하고 자신만의 추상화를 추가할 수 있다는 것을 의미한다.
-
가시성: 시스템의 다른 부분을 얼마나 쉽게 볼 수 있는지를 나타낸다.
차원이 활동에 미치는 영향
검색
검색 시 일부 차원은 중요한 역할을 한다. 예시로 숨겨진 종속성은 검색 활동에 악영향을 미친다. 어떤 코드가 어디에서 호출되는지 몰라 그다음에 코드의 어느 부분을 읽어야 할지 알기 어려워 검색 속도가 느려진다.
이해
이해와 관련되어서는 코드베이스의 가시성이 낮으면 클래스와 기능이 서로 어떻게 연관되어 있는지 파악하기 어렵기 떄문에 부정적이 영향을 준다. 반면 역할 표현력의 경우 변수 및 기타 개체의 유형과 역항이 명확하면 이해하기 더 쉬워진다.
전사
전사 시 일관성 같은 일부 차원이 나빠질 수 있다. 새로운 기능을 구현할 때는 코드베이스에 맞춰야 하므로 정신적 노력이 추가로 필요할 수 있따.
증가
코드베이스에 새 기능을 추가할 때 가장 도움이 되는 것은 매핑 근접성이다. 코드베이스에서 프로그래밍 개념보다는 코드의 목표를 뚜렷이 알 수 있다면, 새로운 코드를 추가하는 것이 더 쉬울 수 있다. 점도가 높은 코드베이스에는 코드를 추가하기 어렵다.
탐구
새로운 설계 아이디어를 탐구할 때 가장 도움이 되는 차원은 잠정성과 점진적 평가다. 힘든 정신 활동과 추상화는 프로그래머에게 높은 인지 부하를 유발하고 해결 공간을 탐구하는 데 사용되어야 할 부하를 제한하기 때문에 탐구에 악영향을 끼칠 수 있다.
트레이드오프의 존재
대부분의 경우 서로 다른 차원 간의 트레이드오프가 이루어져야 한다. 한 차원을 개선하면 다른 차원이 감소한다.
예를 들어 타입을 추가하면 실수를 방지할 수 있지만 사용자에게 추가 작업 부담을 준다. 이는 오류 경향성과 점도에 대한 트레이드 오프가 존재하는 케이스이다. 그리고 타입 애너테이션의 경우 변수 역할을 나타내주지만 코드베이스의 크기를 늘리기 때문에 역할 표현력과 분산성의 트레이드 오프가 존재한다.
설계 기둥
설계 기둥을 통해 프레임워크의 인지 차원에 따라 기존 코드베이스의 설계를 개선하는 것이 이루어질 수 있다. 설계 기둥은 특정 차원을 개선하기 위해 코드베이스를 변경하는 것이다.
예를 들면 코드베이스에 타입 추가하기(오류 경향성 개선), 함수 이름을 코드 영역에 더 부합하도록 변경(매핑 접근성 개선) 같은 거다.
코드베이스가 최적화할 대상인 차원에 대한 요구사항은 수행하려는 활동에 따라 다르다는 점도 중요하다.
새로운 개발자 팀원의 적응 지원
전문가와 초보자는 다르게 생각한다
전문가들은 초보와 다르게 생각하고 행동한다. 전문가는 코드에 대해 추상적으로 추론할 수 있고, 코드 자체를 언급하지 않고도 코드에 대해서 생각할 능력을 가지고 있다. 초보자는 코드의 세부사항에 집중하는 경향이 있고 세부사항에서 벗어나는 데 어려움을 겪는다.
중급 프로그래머들도 새로운 정보를 배우다 보면 초급 수준의 사고방식으로 떨어질 수 있다. 새로운 개념을 배우는 사람들은 추상적인 용어와 구체적인 예시를 모두 배워야 하고, 새로 배운 개념을 기존 지식과 연결할 시간이 필요하다.
새 팀원의 기억 지원
LTM 지원: 관련 정보 설명
코드베이스 작업 시 중요한 역할을 하는 관련 정보를 숙지함으로써 적응 지원 과정을 준비할 수 있다. 도메인과 관련한 중요한 개념 혹은 기타 외부 도구에 대한 정보를 문서화하면 좋다. 기존 개발자의 경우 이와 관련된 지식들을 모두 숙지하고 있지만, 새 팀원의 경우 구체적으로 알지 못해 이해에 어려움을 겪을 수 있다.
STM 지원: 규모가 작고 집중할 수 있는 작업 준비
새 팀원은 코드를 이해하고 기능을 구현하는 등의 일을 수행 중이지만, 코드베이스를 쉽게 탐색할 수 없기에 STM에 과부하를 유발할 수 있다. 코드를 찾는 데 시간을 많이 소요하고 주어진 과제에 집중하기 어렵다. 이를 위해 코드를 이해할 수 있는 활동을 준비하는 게 좋다. 기존 클래스의 요약 작성, 특정 기능 실행에 참여하는 모든 클래스 기록 같은 것들이다.
작업 기억 공간 지원: 도표 그리기
도표 사용을 통해 작업 기억 공간을 지원할 수 있지만, 코드베이스를 처음 사용하는 사람에게는 어려운 일일 수 있다. 따라서 교육자가 기억 공간에 도움이 될 만한 테이블을 만드는 것이 좋을 수 있다.
코드 함께 읽기
적응 지원 과정에서 팀 모두 함께 코드를 협업해서 읽는 활동도 도움이 될 수 있다.코드 파악을 위한 자연어 텍스트 이해의 7가지 기법이 있다. 이를 통해 새 팀원의 인지 부하를 낮춰 그들이 더 많은 작업 기억 공간을 갖고 코드에 집중할 수 있다.
- 활성화: 관련된 것들을 적극적으로 생각해서 이미 가지고 있는 지식 활성화하기
- 모니터링: 텍스트를 읽으면서 자신이 이해한 것을 관찰하고 기록하기(이해하지 못한 부분까지)
- 중요도 결정: 텍스트에서 어느 부분이 중요한지 결정하기
- 추론: 텍스트에서 명시적으로 주어지지 않은 사실을 유추하기
- 시각화: 깊이 있는 이해를 위해 텍스트에 대한 도표 만들기
- 질문: 텍스트에 대한 질문하기
- 요약: 텍스트를 짧게 요약하기