본문 바로가기
프로그래밍/기타

[기타] 가독성(readable) 좋은 코드와 인지 부하(recognite load)에 대한 고찰

by 사바라다 2022. 6. 28.

안녕하세요. 오늘은 가독성 좋은 코드란 어떤 코드인가에 대해 우연히 책을 읽다 공감가는 글을 발견 하였고 스스로의 생각을 정리해보면 좋겠다라는 생각을 가지게 되었습니다. 오늘은 제가 생각하는 가독성 좋은 코드는 어떤 코드인가에 대해서 한번 포스팅하려고 합니다.

코드 작성과 가독성 좋은 코드

코드를 작성할 때 가독성(readability)을 신경쓰면서 작성하는 것은 당연한 이야기 입니다. 가독성 좋은 코드란 그 코드를 읽었을 때 이해하기 쉬운 코드를 뜻합니다. 가독성 좋은 코드를 위한 팁과 내용들은 대표적으로 클린코드라는 책이 있고 또한 조금만 검색해도 가독성을 높이기 위한 많은 자료들이 나옵니다.

실제로 프로젝트를 진행하다보면 새롭게 처음부터 작성하는 경우도 있지만 대부분의 경우 기존의 코드를 수정하거나 기존의 코드를 이용합니다. 따라서 프로젝트를 진행하기 위해서는 기존의 코드를 이해하고 해석하는데 시간이 드는데 소요되는 시간이 로버트 마틴이 말하길 1 : 10의 비율정도 된다고 합니다. 제 생각에도 작업을 진행하기에 앞서서 기존 코드에 대한 정확한 분석을 하는데 이 때 이 정도의 비율로 시간이 소모된다고 생각합니다.

가독성과 인지 부하

간단하게 가독성에 대해서 위해서 잠깐 이야기 해보았습니다. 인지 부하(recognite load)라는 개념을 설명하기의 앞선 이야기로 잠깐 이야기했는데요. 이 개념은 제가 최근에 이펙티브 코틀린이란 책을 보다 얻게 된 개념이며 이에 대한 설명은 함께 공유드리면 좋을것 같아서 재정리하여 이렇게 포스팅으로 작성해봅니다.

위키백과에 따르면 인지 부하(cognitive load)는 학습이나 과제 해결 과정에서의 인지적 요구량을 말한다. 어떤 정보가 학습되기 위해서는 작동기억 안에서 정보가 처리되어야 하는데, 작동기억이 처리해 낼 수 있는 정보의 양보다 처리해야 할 정보가 많으면 문제가 생기며 인지부하가 생기게 된다.

이를 가독성에 대입해보면 가독성 좋은 코드는 작성한 코드를 읽는 사람의 숙련도에 의해서 좌우될 수 있다는 뜻입니다. 또한 동일한 방법으로 항상 좋은 가독성을 가지기는 어렵고 경우에 따라서 가독성 좋은 코드의 작성 방법이 다른 경우(다른 문제의 상황)에는 좋지 않을 경우도 있을 수 있다고 이해해주시면 될 것 같습니다. 아래의 예제를 한번 보도록 하겠습니다.

fun A() {
    if (person != null && person.isAdult) {
        view.showPerson(person)
    } else {
        view.showError()
    }
}

fun B() {
    person?.takeIf { it.isAdult }
        ?.let(view::showPerson)
        ?: view.showError()
}

책에 재미있는 예제와 말이 나옵니다. 과연 A 메서드와 B 메서드 중 어떤 메서드가 좀 더 가독성(Readability)가 좋은 코드일까요 ? 저는 처음 이 질문을 받았을 때 코틀린에서 제공하는 기술들을 활용하여 더 깔끔하게 정리한 B가 가독성이 더 좋은 코드가 아닐까 ? 라고 생각했었습니다. 하지만 책에서는 A가 더 가독성이 좋은 코드라고 합니다.

어떠한 이유인지 보니 책에서는 아래와 같이 설명하고 있었습니다.

가독성이란 코드를 읽고 빠르게 이해할 수 있는지를 의미합니다. 이는 우리의 뇌가 얼마나 많은 관용구(구조, 함수, 패턴)에 익숙해져 있는지에 따라서 다릅니다. 코틀린 초보자에게는 구현 A가 더 읽고 이해하기 쉽습니다. 일반적인 관용구(if/else, &&, 메서드 호출)를 사용하고 있기 때문입니다. 구현 B는 코틀린에서는 꽤 일반적으로 사용되는 관용구(안전 호출 ?., takeIf, let, Elivis 연산자, 함수 레퍼런스 view::showPerson)를 사용하고 있습니다. 코틀린에서 일반적으로 사용되는 관용구이므로, 경험이 많은 코틀린 개발자라면 그래도 코드를 쉽게 읽을 수 있을 것입니다. 하지만 숙련된 개발자만을 위한 콛드는 좋은 코드가 아닙니다. 구현 A와 구현 B는 사실 비교조차 할 수 없을 정도로 훨씬 가독성이 좋은 코드입니다.

이러한 이유로 저자는 A가 더 좋은 가독성을 가지고 있는 코드라고 말합니다. 중요한 것은 사용 빈도가 적은 관용구는 코드를 복잡하게 만들고 그리고 이러한 관용구를 섞어 쓴다면 복잡도는 더하기가 아닌 곱하기로 증가할 것입니다. 따라서 이런 부분을 신경써서 코드를 작성할 필요가 있습니다.

그렇다고 빈도가 적은 관용구는 사용하지 말아야된다라는 것은 아닙니다. 이 또한 잘 사용하면 충분히 가독성을 올려줄 수 있습니다. 항상 적절한것이 중요합니다. 아래에서 또 다른 예제 하나를 보도록 하겠습니다.

var obj = FileInputStream("/file.gz")
  .let(::BufferedInputStream)
  .let(::ZipInputStream)
  .let(::OjbectInputStream)
  .readObject() as SomeOjbect

위 코드는 코틀린의 관용구를 주로 사용했지만 가독성이 나쁘지만은 않습니다. 파일을 읽어서 Object로 만들어내기까지의 과정을 Stream의 map 처럼 간결하게 표현했기 때문입니다. 이 처럼 어떻게 가독성있게 코딩할 수 있는가는 상황에 따라 다릅니다. 때문에 한쪽으로 치우쳐서 생각하는 것은 피해야 할 것입니다.

마무리

오늘은 이렇게 가독성 좋은 코드를 작성함에 있어서 인지 부하와 엮에서 고민해보았던 부분을 공유하는 포스팅을 작성해보았습니다.

해당 포스팅은 개인마다 생각하는 바가 다를 수 있습니다. 저의 개인적인 생각이니 본인의 생각과 충분히 다를 수 있습니다.

감사합니다.

참조

[1] 이펙티브 코틀린 2장 가독성

[2] https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%A7%80_%EB%B6%80%ED%95%98

[3] https://blog.alexdevero.com/6-simple-tips-writing-clean-code/

댓글