미리 검증할 수 있는

구경회·2020년 11월 30일
3
post-thumbnail

무너질지 그렇지 않을지를 미리 알 수 없는 건축물은 없다. 이 건물이 무너질까에 대한 답이, "지어봐야 알 수 있습니다."이면 얼마나 황당하겠는가? 하지만 소프트웨어 세상에는 그런 일이 너무나도 잦다. 이 문제를 해결하기 위해 도입된 것이 더 높은 수준의 타입 시스템이다.

예를 들어, 다음과 같은 자바스크립트 코드를 보자.

let x = 4
let y = x + "!"
y // "4!"

얼마나 황당한 일인가? 문자열에 수를 더하는 연산이 매우 자연스럽게 이루어진다. 이와 같은 암묵적 타입 캐스팅은 프로그래머의 골치를 아프게 한다. 그 외에도 JS 속에 숨어있는 함정은 한두개가 아니지만 넘어가자.

하지만, 그렇다고 타입이 답인가? 타입을 명시하는 대표적 언어인 C(C++), JAVA의 verbose함은 악명이 높다. 아래는 재료역학 과제 당시 짰던 프로그램 중 일부이다. 여러 타입 힌트가 들어가 있는 것을 확인할 수 있다. 물론 C++의 현대적인 요소들을 알고, 좀 더 C++에 대해 깊은 이해를 한다면 간명하게 작성할 수 있다. 그러나 프로그래머가 의식적으로 노력해야 그런 코드를 짤 수 있는 언어와 언어 차원에서 강제하는 것은 차원이 다르다.

std::pair<double, double> calcTriAngle(Beam &beam, double q, double k1, double k2, bool leftHigher) {
    double c = beam.to->x - k2, a = k1 - beam.from->x, b = k2 - k1;
    double l = beam.to->x - beam.from->x, d = a + b;
    double tmp = (q * b) / (12 * beam.E * beam.I * l);
    std::pair<double, double> ans(0, 0);
    if(leftHigher) {
        ans = calcSquareAngle(beam, q, k1, k2);
        ans = ans - calcTriAngle(beam, q, k1, k2, false);
    } else { // right is higher
        double e = l - a - ((double) 2 / 3) * b;
        ans.first = tmp * (-1 * e * std::pow(l, 2) + std::pow(e, 3)
            + (std::pow(b, 2) / 6) * (c + ((double) 17 / 45) * b)
        );
        ans.second = l * tmp * ( 2 * e * l + std::pow(e, 2) * ((e / l) - 3)
            + (std::pow(b, 2) / (6 * l)) * (((double) 17 / 45) * b - d)
        );
    }
    

반면, 아래와 같은 스칼라 코드는 훨씬 더 읽기 좋고, 버그가 생길 가능성도 적다.

val authUser: Kleisli[OptionT[IO, *], Request[IO], User] = 
  Kleisli { req =>
    val hs: Option[User] = for {
      token <- req.headers.get(CaseInsensitiveString("Token"))
      res <- checkToken(token.value)
    } yield { res }
    OptionT.fromOption(hs)
  }

이러한 흐름을 따라, C++, JAVA등은 auto, decltype나 var 등을 통해 자동적인 타입추론을 제공하고 있고 (물론 아주 훌륭하지는 않다) js는 타입스크립트를 활용하는 것이 점점 보편화 되어가고 있다. 파이썬 또한 타입 추론을 명시하는 방향으로 나아가고 있다.

하지만 우리가 평소에 듣는 수업 등에서는 과거의 유산이라 할 수 있는 저급 언어를 사용하거나, 그러한 언어들을 사용할 때도 새로운 feature들 보다는 과거의 유산에 머물러 있는 경우가 많다. 예를 들어, C++11조차 사용하지 않는 수업을 듣는다면 C++을 단순히 더 나아진 C쯤으로 취급하는 것이 당연하지 않을까? 람다표현식, auto 등의 위력을 느끼지 못한 채 말이다.

Ocaml, Haskell, Scala, Kotlin 등 더 나은 타입시스템을 갖춘 언어들을 사용하며 좀 더 나은 안목을 기르고, 좀 더 나은 프로그래머로 나아가자.

profile
즐기는 거야

0개의 댓글