Skip to main content

프로그래머의 뇌

· 28 min read
Dongle

인지과학으로 프로그래머의 입장에서 뇌가 어떻게 반응하는지를 한 번 생각 해 볼 수 있는 책

프로그래머의 뇌

이 책의 목적은 두뇌가 코드를 처리하는 방식을 이해하도록 돕는 것이다.

코드 잘읽기

코드가 초래하는 세 가지 종류의 혼란

  1. 지식의 부족
    • LTM (long-term-memory) 장기 기억 공간에 내용이 없다는 것.
      • 반영구적으로 저장하는 곳이다.
  2. 정보의 부족
    • STM(short-term memory) 단기 기억 공간에 내용이 없다는 것.
      • 정보를 수집할 때 단기 기억 장소에 일시적으로 저장하지만, 다른 정보를 찾는 과정에서 이미 수집해놓은 정보 중 일부는 잊어 버린다.
  3. 처리능력의 부족
    • WM(working memory)
      • 많은 정보를 처리할 때 사용

트레이싱

  • 머리속에서 코드를 컴파일하고 실행하는 과정을 의미한다.

프로그래밍 업무와 관련한 인지 사항

버그 리포트로 받는 경우 버그를 고치기위해 몇개월 전 작성한 코드를 다시 읽어야한다.
코드 분석을 할 때 읽는 내용은 STM에 저장되며, 몇 개월 전에 구현한 내용을 LTM에서 가져올 것이다.과거의 경험으로 기억된 내용뿐만아니라 오류의 해결법 같은 정보 역시 LTM에 저장되어 있다.
이 모든 정보, 즉 STM에 저장된 새로운 버그 리포트 내용, 그리고 LTM에 저장된 유사한 버그의 해결법이나 개인적인 기억 두 가지가 다 작업 기억 공간으로 들어오게 되고, 그제서야 당면 문제에 대해 생각 할 수 있게 된다.

세 가지 인지 과정

  1. LTM에서 정보를 인출, 키워드의 의미 같은 것들이 해당
  2. 메서드나 변수의 이름과 같이 코드를 읽는 과정에서 발생하는 정보를 STM 일시적으로 저장
  3. WM 에서 일어 나는데 코드를 읽고 처리하는 일이 여기서 이루어지는데 예를 들면 ‘인덱스 값이 하나 작다’라고 판단하는 것이다.
  4. 서로서로 이 3가지 과정은 보완적으로 작용한다. STM이 n과 같은 변수명을 보게 되면 과거에 읽었던 그와 관련된 프로그램을 LTM으로부터 찾는다. 모호한 단어를 보면 WM이 활성화되며 문맥 속에서 적합한 의미를 찾으려 한다.

컴퓨터와 마찬가지로 인간의 STM인지 능력은 LTM보다 훨씬 적다.


청크단위

이미지를 청크단위로 기억을 해서 우리는 STM을 더 효율적으로 사용 할 수 있다.

Ozpq odfj vs like love

생소한 문자로 글을 작성하면 STM에 저장하는데 한계가 있지만, 뒤에 문자는 여러 개의 문자를 한 단위로 묶어서 기억 했기 때문에 쉽게 기억이 가능하다.


코드에서 청킹

디자인패턴이 한 요소가 될 수 있다.


주석문

일반적으로 개발자들은 주석문을 포함하고 있으면 코드를 읽는 시간이 더 많이 들어간다고 한다. 하지만 이는 개발자들이 주석문을 읽는다는 사실을 시사한다. 이것은 최소한 의미없는 일이 아니라는 것을 보여준다. 코르시비의 연구에 따르면 코드에 주석문이 있으면 새로운 팀원이 코드를 쉽게 이해할 수 있다라고 한다.

주석문은 초급 개발자가 코드를 이해하는 데도 도움이 되지만, 개발자가 코드를 청킹하는 방식에도 영향을 미친다. 취인 판의 연구에 따르면 개발자들은 코드를 읽을 때 주석문에 굉장히 많이 의존한다. 특히 이 함수는 주어진 이진 트리를 중위 순회하며 프린트한다. 같은 고수준 주석문은 코드를 청크 단위로 쪼개는 데 도움이 된다. 반면 i++; 다음에 i를 1만큼 증가’ 같은 저수준 주석문을 넣는 것은 오히려 청킨 작업에 부담이 된다.


청킹 연습

의도적 연습(deliberate practice)은 어떤 기술을 향상하기 위해 조금씩 연습하는 것을 의미.

  1. 코드 선정
    • 어느 정도 익숙해져 있는 코드베이스를 하나 고르기. 정기적으로 작업하지만 주로 작업하지 않는 코드베이스면 좋다. 본인이 오래전에 작성한 코드라도 상관없다. 최대 50라인을 넘지 않도록 해야 한다.
  2. 코드 파악
    • 2분을 넘지 않도록 타이머를 설정하고 코드를 파악해라. 시간이 다 되면 코드는 보지 않는다.
  3. 코드 재현
    • IDE에 기억을 되살려 코드를 작성해보자
  4. 회고
    • 어느 부분을 쉽게 기억했는가?
    • 부분적으로 기억한 코드가 있는가?
    • 전체를 다 기억하지 못한 코드가 있는가?
    • 기억하지 못한 라인들이 있다면 그 이유는 무엇일까?
    • 기억하지 못한 라인에 본인이 익숙하지 않은 프로그래밍 개념 들어 있지 않는가?
    • 기억하지 못한 라인에 본인이 익숙하지 않은 도메인 지식이 있나?

option으로 다른사람이랑 같이 비교해보는 것도 좋다. 자신의 실력을 판단 할 수 있는 근거가 될 수 있다.

자료구조, 디자인패턴, 문법을 아는 부분이 중요한 이유가 코를 효율적으로 읽고 이해하는데 상당한 영향을 미친다. ← STM에 해당하는 부분


업무 중단이 미치는 나쁜 영향

파닌 교수는 업무 도중 주단이 되면 프로그래머에 어떤 일이 일어나는지 연구 했고 업무 중 도중 중단이 되고 되돌아 가는데 15분 정도 걸렸다고 한다.(p.38)

이건 평소 내가 생각했던 생각이랑 다른 시각인데 난 평소에 문법을 검색을 하면 되지 않나? 대충 알고만 있으면 검색을 해서 적용 할 수 있지 않나라고 생각을 할 수 있지만 이게 계속 반복되다보면 다시 일을 복귀 할 때 컨텍스트 스위칭이 내 생각보다 오래 걸릴 수도 있다는 개념이 신선했다.


문법을 빠르게 배우는 법

플래시카드 기법 앞에 암기하려고 하는 내용에 대한 프롬포트, 즉 그것을 지칭하는 단어나 질문이 있고 뒷면에는 그에 대한 내용이나 답이 있다.

ex) 기본 문법 → numbers = [ x for x in numbers]

  필터         → odd_numbers = [x for x in numbers if x % 2 = 1 ]

플래시카드 기법은 내가 새로운 업무에 조인을 할 때도 유용할 거 같다. 특히 새로운 도메인 안익숙한 도메인에 조인을 할 때도 새로운 개념이 나오면 알아야하는 용어들을 앞에 적고 뒤에 적는 방식으로 조금 더 빠르게 개념을 이해 할 수 있을 거 같다. (이번주에 적용 해보기!)

일반적으로 STM에 있는 것들을 LTM에 집어 넣으려면 한 달에 한 번씩 복습을 해야한다.

정보를 외우는 것은 기억을 강화한다.

인출 강도

  • 무언가를 기억해내려고 할 때 나오는 강도
    • filter() 함수를 기억을 하고 잇지만 막상 잘 기억을 못한다면 인출강도가 낮도가 얘기한다.
    • 시간이 흐를수록 약해진다

저장 강도

  • LTM에 얼마나 잘 저장하고 있는가를 나타낸다.

인출을 하려고 노력을 해야한다.
능동적으로 생각을 할 때 인출의 강도는 높아진다.
너무 쉽게 정보를 찾고 또 그것이 너무 일상적으로 이뤄지다 보니 우리 두뇌는 문법을 기억할 필요가 없다고 느낀다.

구글 검색하기 전에 먼저 능동적으로 의도적으로 기억하려고 시도해보자. 항상 떠올리려고 생각을 해야 내 것이 되는거 같다는 걸 많이 느꼈었다.

프로그래밍 개념을 새로 배울 때 적용 해볼 만 한 내용

  • 새로운 개념이 어떤 다른 개념을 생각나게 했는가? 적어보기
  • 위에서 적은 관련된 개념에 대해 다음 질문에 답해보기
    • 새로운 개념은 왜 이미 알고 있는 그 개념을 생각나게 했을까?
    • 문법에 공통적인 점이 있는가?
    • 비슷한 환경에서 사용될 수 있는가?
    • 이 새로운 개념은 이미 알고 있는 그 개념 대신 사용될 수 있는가?
    • 동일한 목적을 달성하기 이해 작성할 수 있는 다른 방법을 코드를 알고 있는가? 같은 결과를 갖는 비슷한 코드를 최대한 많이 만들어봐라.
    • 다른 프로그래밍 언어에서 같은 개념이 있는가? 비슷한 동작을 수행하는 다른 언어의 예제 코드를 작성할 수 있는가? 서로 어떻게 다른가?

인지 부하

인지 부하에는 크게 내재적 인지부하 외재적 인지부하가 있다.
내재적 인지 부하는 내가 이지식을 알고 있냐 모르고 있냐의 차이고
외재적 인지 부하는 지식은 있지만 그걸 적용 할 때 따르는 부하이다.
ex) ( for int v = i / 2; ; v++;) for 문을 알고 있지만 그 안에 내용이 생소할 경우 나타나는 부하이다.


인지 부하를 줄이는 법

  1. 리팩터링
  2. 코드를 여러번 읽어도 이해가 안된다면 어디서 부터 중점을 두고 읽어야할지 모르는 것이다. 큰 그림을 이해 못 한거일 것이다. 이럴 땐 보조수단을 사용하면 좋다.
    • 의존그래프를 그려보자
    • 정 이해가 안되면 프린트해서 원을 그려보자
    • 원을 연결하고 선을 이어서 보자

알고리즘 공부할 떄 써먹을 수 있겠다. 상태표를 그리고 그안에 나타나는 모든 변수들을 기입하자. 그리고 그 안에서의 흐름을 적어보자 loop문을 적고 그 때의 나타나는 변환을 적어보자. tip 어떤 변수는 생략하고 지나가고 싶을 때 생략하지말고 최대한 자세히 적자.

코드 잘 읽기

기존 지식의 활성화

익숙하지 않은 코드를 미리 정한 시간, 5분이나 10분 정도만 봐라 그리고 다음과 같이 질문을 하라

  • 가장 먼저 시선을 끈 코드 구성요소(변수, 클래스, 프로그래밍 개념등)은 무엇인가?
  • 왜 그런가?
  • 두 번째로 주의를 끈 것은 무엇인가?
  • 왜 그런가?
  • 그 두 가지(변수 ,클래스 , 프로그래밍 개념 등)는 서로 관련이 있는가?
  • 코드에 어떤 개념들이 존재하는가? 그 개념 요소들은 다 알고 있는가?
  • 코드에 어떤 문법 요소들이 존재하는가? 그 문법 요소들은 다 알고 있는가?
  • 코드에 어떤 도메인 개념들이 존재하는가? 그것들을 다 알고 잇는가?

모니터링

코드를 읽을 때는 무엇을 읽고 있는지, 이해는 하고 잇는지를 계속 추적 하는것이 중요하다. 코드를 프린트를 해서 이해되는 라인과 이해되지 않는 라인을 표시하는 것도 좋은 방법이다.


코드리뷰할 때 적용 해볼 수 있는 요소

  • 코드 작성자가 내린 결정 사항이 무엇인가? 에를 들어 특정 라이브러리나 api를 사용하기로 한 결정, 자료구조, 특정 디자인패턴 등
  • 그런 결정을 내리는 데 상정한 가정은 무엇인가
  • 그 결정의 효과는 ?
  • 그 결정의 잠재적 위험 요소는 무엇인가
  • 다른 해결책으로 어떤 것이 있을까?

정신 모델

문제에 대해 생각할 때 두뇌의 외부에서 만들어지지 않은 모델을 말함. 폴더 구조를 생각 할 때를 예로 들 수 있는데 실제로는 0과 1로 이루어 졌지만 모델로 입혀서 생각을 할 때라고 생각하면된다. 잘못된 정신모델이 LTM에서 완전히 제거가 안되고 남아있을 수 있다.

복잡한 코드에 대한 정신 모델 작업

  1. 국지적 모델을 만든다.
    • 큰 개념을 먼저 만든다.
    • 서로 밀접하게 관련되어 있는 라인을 하나의 의존 그래프로 나타낸다고 할 때 이 의존 그래프는 정신 모델을 형성하는 데 중요한 역할을 할 수 있다.
  2. 코드에서 관련된 모든 객체와 객체 간의 관계를 나열한다.
    • 코드내에서 객체간에 상호작용을 화이트보드나 디지털 도구를 사용하여 구성 요소를 나열한 다음 그들 사이의 관계를 찾아야 한다.
  3. 시스템에 대한 질문을 만들고 이 질문의 답을 사용해서 모델을 개선한다.
    • 시스템에서 가장 중요한 요소는 무엇인가? 모델에 그것들이 포함되어 있나?
    • 이 중요한 요소들 사이의 관계는 무엇인가?
      • 내가 생각 했을 땐 쿠폰이라는 큰 개념이 있고 그 쿠폰에 해당하는 여러 사항들 사용자는 하나의 쿠폰만 쓸 수 있다. 이런 요소요소들의 관계를 적어야한다.
    • 프로그램의 주요 목표는 무엇인가?
    • 목표가 핵심 요소 및 그 관계와 어떻게 관련되어 있는가?
    • 일반적인 사용 사례는 무엇인가? 모델이 그것을 보여주는가?

개념적기계

  • 스키타마 - LTM이 정보를 저장하는 방식이다. 연상을 하고 집어 넣으면 거기에 맞게 조금 더 쉽게 이해를 할 수 있다. 예를 들어 변수를 상자로 설명을 하는 식의 그러나 이러한 점은 때로는 안좋을 수가 있는데 박스에는 여러 값들이 들어갈 수도 있다. 밀접한 정식 모델을 가지고 있으면 (변수 - 상자) 조금 더 외우기 쉬워진다 반대로 뜬금없이 외발자전거 - 변수 이렇게 연관해버리면 이해하기가 어렵다

새로운 언어를 배울 때

새로운 언어를 배우면 기존에 알고 있던 언어를 LTM에서 유사한 점을 가져와서 STM을 적게 사용하고 작업공간을 효율적으로 사용을해서 조금 더 사용 할 수 있다. 또한 작업에 대한 감정이 좋았었다면 새로운 작업이 주어 졌을 때 과거에 사용했던 알고리즘, 여러 같은 방식을 사용하게 될 확률이 높다.

앞에가 긍정적 전이였으면, 부정적 전이도 있다. 오히려 한 언어에서 다른 언어로의 부정적 전이가 될 수 있다.

꼭 여러 언어를 안다고 지능이 높아지는 건 아니다(체스선수의 예로… )

공통점과 차이점에 의식적으로 주의를 기울이면 새로운 언어를 배우는 일이 쉬워질 것이다.

                      유사점              차이점             비고 
  1. 문법
  2. 타입
  3. 프로그래밍 개념
  4. 런타임
  5. ide
  6. 테스트 방식

오개념

자신이 옳다고 확신하지만 실제로는 틀릴 때 오개념을 갖게 된다. 오개념은 단순히 자신이 틀렸다는 것을 꺠닫거나 듣는 것만으로는 해결되지 않는다. 오래되고 잘못된 정신모델을 대체할 새로운 모델이 필요하다.

고기의 표면이 타면 수분은 오히려 날라간다! 알고 있는 거와 다르게 수분 손실이 더욱 크다.

알고있는 언어에서 새로운 언어를 배울 때 기존의 지식을 떨쳐내기 위해 많은 에너지를 소비해야 한다. 개념적인 변화가 필요하기 때문에 시간이 오래걸린다. 우리가 똑똑하지! 못해서가 아니라 부정적인 전이가 돼서 그렇다.


오개념 방지하기

자신이 옳다고 확신하더라도 여전히 틀릴 수도 있따는 것을 아는 것이 중요하다. 열린 마음

흔하게 발생하는 오개념에 대해 의도적으로 연구해봄으로써 그런 오개념에 빠지는 것을 방지 할수 있다. 오개념들에 대한 체크리스트를 사용하는 것이 도움이 될 수 있다. 같은 프로그래밍 언어를 같은 순서로 학습한 다른 프로그래머들에게 조언을 구하는 것이다.


검색을 할 때

검색은 STM에 무리가 간다. 그래서 이러한 부하를 줄이기 위해 별도의 문서나 노트를 작성하면 도움이 된다. 만약 코드 내에서 살펴 볼 때는 특정 코드를 살펴본 이유를 주석문으로 작성해놓으면 도움이 된다. 나중에 동일한 코드를 검색하고 확인할 때 도움이 될 수 있다.


업무 중단에 잘 대비하는 법

  1. 정신모델 저장
    • 코드를 작성 중에 잠시 중단요청이 들어 옸다면 주석문을 작성하자. 그러면 나중에 작업을 쉽게 재개할 수 있다.
  2. 미래 기억 향상
    • 계획을 완성 할 수 없다면 TODO 문을 적극적으로 사용하자. 기한을 정해 놓으면 더 좋다.
  3. 하위 목표 라벨 붙이기
    • 하위 목표를 잘 나누자. 큰 부분에 일을 작은 부분의 문제로 쪼개 놓자.

멀티테스킹

인스턴트 메신저(페이스북) 특히 메세지를 받는 즉시 답장한다고 응답한 학생들이 상대적으로 매우 생산적이라고느끼지만 수행 능력은 떨어졌다.

방해를 받더라도 가급적이면 인지 부하가 낮을 때 중단이 일어나도록 해야 한다. 예를 들어 슬랙에서 상태를 설정한다던지.


새로운 뉴비 개발자 온보딩

흔한 문제점으로 새로온 뉴비 개발자에게 한 번에 많은 정보들을 준다. 예를 들어 코드베이스, 도메인, 워크플로 등 여러가지 많은 정보를 주게 되는데 이는 인지 과부화를 초래하여 새로운 정보를 기억할 공간이 없어서 적응에 어려움을 겪게 된다. 그리고 새 팀원에게 질문을 하거나 과제를 주게 되는데 선임 개발자는 이것이 그냥 흔한 작은 버그를 고치는 과제였겠지만 이는 양쪽 모두 좌절감을 주게 된다. 새로운 팀원은 매우 어려운 프로젝트라고 생각이되고 선임 팀원은 똑독하지 않다고 생각이 되며, 이는 팀워크가 앞으로 잘 이뤄질 것이라고 기대하기 어렵다.


작업은 하나의 프로그래밍 활동으로만 제한

탐구 - 코드베이스의 전체적인 이해를 위한 코드 훑어보기 검색 - 특정 인터페이스를 구현한 클래스 찾기 전사 - 구현할 메서드에 대한 명확한 계획을 알려주기 이해 - 코드의 여러 측면에 대해 이해하기, 예를 들면 특정 메서드를 요약하기 증가 - 향후 계획을 포함해서 기존 클래스에 한 가지 기능을 추가하기 적응 기간에는, 구체적으로 다섯 가지 범주 각각에 해당하는 활동을 선택하고 새 팀원에게 하씩 시키는 것이 가장 좋다.

만드는 것보다 이해를 하는 것이 더 좋을 떄도 있다

  • 새 팀원이 코드의 특정 부분을 이해하길 원하면 구현 작업 대신, 해당 코드를 이해하도록 요청해야 한다. 예를 들어 기존 클래스의 요약을 작성하거나 특정 기능이 실행에 참여하는 모든 클래스를 기록하도록 요청한다.

새로운 개념을 배우는 사람들은 추상적인 용어와 구체적인 에를 모두 배울 필요가 있다. 또한 새로 배운 개념을 기존 지식과 연결할 시간이 필요하다.


후기