이제 Lisp의 저주가 여러분의 생태계에도 찾아옵니다

The Lisp curse, now coming to your ecosystem

javahippie.net ▲ 238 댓글 206 marcolinux

요약

LLM으로 코드를 만들기 쉬워지면 Lisp의 저주처럼 라이브러리 생태계가 약해질 수 있습니다.

개발자 팀 쵤러가 자기 블로그에 쓴 글입니다. Lisp의 저주는 언어가 너무 강력해 저마다 직접 만들어 쓰다 보니 공유 라이브러리가 드물다는 설명입니다. 그는 LLM 코딩이 자바 같은 주류 생태계에도 같은 일을 부를 수 있다고 봤습니다.

왜 중요한가

  • 라이브러리를 찾는 것보다 코드를 생성하는 쪽이 싸지면 오픈소스의 사용자와 기여자가 함께 줄 수 있다는 경고입니다.
  • 그는 극적인 붕괴보다 모르는 사이에 협업이 줄고 개발이 더 외로운 일이 되는 쪽을 걱정했습니다.

핵심 내용

  • 프롬프트 한두 번이면 될 일에 라이브러리를 찾거나 문서를 읽지 않게 되어 관리자에게 가는 피드백이 준다고 봤습니다.
  • 오픈소스에서 정말 힘든 일은 배포, 버전 관리, 하위 호환성 유지 같은 뒷일이라고 짚었습니다.
  • 자기 필요에 딱 맞는 코드를 생성할 수 있으면 이런 짐을 지고 라이브러리를 낼 이유가 사라진다고 했습니다.
  • 새 기술을 들여오는 라이브러리가 줄면 개발자는 더 직접 생성하게 되어 두 흐름이 서로를 키운다고 봤습니다.
  • 그는 수백 줄의 생성 코드보다 검증된 라이브러리를 택하겠다며, 생성 코드만 믿는 태도를 'Not invented here' 증후군의 새 버전이라고 했습니다.

HN 반응

  • 에이전트로 오픈소스 버그를 고쳐 놓고도 직접 검토하지 않은 코드라 기여하지 않는다는 경험담이 여럿 나와 글의 우려를 뒷받침했습니다.
  • Common Lisp 생태계는 SBCL과 주요 라이브러리 기여가 활발하다는 반론과, 남이 관리하는 라이브러리를 원하는 사람에게는 여전히 척박하다는 반박이 맞섰습니다.

댓글

30개 표시 · 전체 206개
  1. vindarel HN

    진짜 "[Common] Lisp의 저주"는 한번 맛을 보면 다시는 돌아갈 수 없다는 거예요.

    그것만 빼면 Common Lisp 생태계는 아주 잘 굴러가고 있다고요. SBCL에 기여하는 사람도 많고, 중요한 생태계 라이브러리에도 꾸준히 기여가 들어오고, 활발한 프로젝트(Lem)도 있고, 새 에디터(제가 만든 거예요)와 플러그인(OLIVE)도 나오고, Lisp를 채택해서 생태계를 어떻게든 후원하는(컨퍼런스를 열거나 구현체 개발자와 계약을 맺는) 회사들도 있어요. https://github.com/CodyReichert/awesome-cl/ · https://github.com/azzamsa/awesome-lisp-companies/ 그리고 네, 바이브 코딩으로 만든 새 프로젝트도 있어요. ICL, cl-tuition처럼 쓸 만한 것도 있고, 바퀴를 (엉망으로) 다시 발명하다가 아무 데도 못 간 것도 있고요. 어떤 건 두고 봐야죠.

  2. rmunn HN

    mine 에디터를 언급하셨으니 Coalton을 아실 텐데, 언급이 없으셔서 제가 여기서 소개하겠습니다. Coalton은 Common Lisp 위에 정적 타입, 타입 추론, Haskell 스타일의 타입클래스(typeclass)를 얹어 주는 Lisp 라이브러리입니다. (타입클래스를 처음 접하신다면, 가장 익숙한 객체지향 언어의 인터페이스를 떠올리시면 됩니다. 타입클래스는 인터페이스가 원래 이랬어야 했다 싶은 물건입니다. 인터페이스가 하는 일은 전부 하고, 인터페이스가 못 하는 일도 많이 합니다.) 아래는 Coalton 문서에 나오는 예제인데, 설명이 따로 필요 없을 만큼 직관적입니다. 더 보고 싶으시면 https://coalton-lang.github.io/manual/topics/whirlwind-tour/ 를 읽어 보세요.

        (coalton-toplevel
          ;; Type classes are defined with the define-class keyword
          (define-class (Eq :a)
            (== (:a * :a -> Boolean)))
    
    (define-type Color
            Red
            Green
            Blue)
    
    ;; Type class instances are defined with the define-instance keyword
          (define-instance (Eq Color)
            (define (== a b)
              (match (Tuple a b)
                ((Tuple (Red) (Red)) True)
                ((Tuple (Blue) (Blue)) True)
                ((Tuple (Green) (Green)) True)
                (_ False))))
    
    ;; Type declarations can have constraints
          (declare is-eql (Eq :a => (:a * :a -> String)))
          (define (is-eql a b)
            (if (== a b)
              "They are equal"
              "They are not equal"))
    
    ;; Multiple constraints must be wrapped in parentheses
          (declare double-is-eql ((Eq :a) (Eq :b) => (:a * :a * :b * :b -> String)))
          (define (double-is-eql a b c d)
            (if (and (== a b) (== c d))
              "Both pairs are equal"
              "The pairs are not both equal")))
    
  3. rmunn HN

    타입클래스를 처음 접하는 분께는 이 예제가 제 생각만큼 직관적이지 않을 수 있겠다 싶어서, 예제를 조금 설명해 보겠습니다.

    (define-class (Eq :a) ...) 블록은 타입 매개변수 :a를 받는 Eq라는 타입클래스를 정의합니다. 나중에 덧붙일 수 있는 인터페이스라고 생각하시면 됩니다. 대부분의(전부일까요?) 객체지향 언어에서는 클래스를 선언할 때만 인터페이스를 선언할 수 있지만, Haskell과 Haskell에서 많은 영감을 받은 Coalton에서는 라이브러리에서 가져온 타입을 포함해 이미 존재하는 어떤 타입에든 "인터페이스"(타입클래스)를 선언할 수 있습니다. 여기서 Eq :a 인터페이스는 :a 타입 매개변수 두 개를 받아 Boolean을 돌려주는 ==라는 함수가 있어야 한다는 뜻입니다(Lisp에서는 연산자도 함수로 정의합니다).

    (define-type Color ...)는 단순한 열거형 타입을 정의합니다(물론 훨씬 많은 걸 할 수 있지만, 이 예제는 단순하게 만들었습니다). 그다음 (define-instance (Eq Color) ...)는 "Color라는 타입은 Eq라는 타입클래스(인터페이스)의 인스턴스다"라는 말입니다. Eq는 ==라는 함수를 요구하므로, define-instance 블록 안에서 Color 타입용 ==를 정의해야 합니다. 패턴 매칭은 설명이 필요 없을 만큼 간단하다고 생각합니다.

    인터페이스보다 더 강력한 점은 이미 한 번 언급했습니다. 여기서는 Color 타입을 선언하고 바로 이어서 타입클래스 인스턴스를 정의했는데, 새 타입을 만들 때 코드를 한곳에 모아 두는 보통의 방식입니다. 하지만 Color 타입이 여러분이 가져다 쓴 다른 라이브러리에서 온 것이었더라도 "아, 이 Color 타입은 Eq를 구현해요. Color 값에 적용되는 ==는 이렇게 정의하고요"라고 말할 수 있습니다. 라이브러리 작성자가 미리 생각해 둔 인터페이스에만 묶이지 않는다는 겁니다. 남이 만든 코드에 인터페이스를 덧붙일 수 있습니다! C#에서 이게 되면 좋겠다고 절실히 바랐던 적이 여러 번 있습니다.

    마지막으로, => 화살표 앞의 제약은 함수 매개변수를 public T isEqual<T>(T a, T b) where T : IEquatable처럼 선언하는 것과 비슷합니다. 덕분에 Coalton은 == 함수가 정의되지 않은 타입의 매개변수로 is-eql을 호출하는 코드를 컴파일 시점에 잡아낼 수 있습니다.

    더 많은 내용은 https://coalton-lang.github.io/manual/topics/whirlwind-tour/ 에 있습니다.

  4. xedrac HN

    자세히 설명해 주셔서 고맙습니다. 저는 Haskell에 아주 익숙해서 전부 자연스럽게 읽히네요. 실제로 쓰면 타입 추론은 얼마나 좋습니까? Haskell만큼 좋습니까? 그리고 일반 Common Lisp를 쓰는 편이 더 나은 경우도 있습니까?

  5. reikonomusha HN

    추론은 Haskell과 대체로 같은 알고리즘과 타입 시스템을 씁니다(Haskell의 어떤 방언이냐에 따라 다르지만요. GHC에는 확장이 정말 많으니까요). 표준 Haskell 타입 시스템에 있는 건 전부 지원하고, 다중 매개변수 타입클래스, 함수적 종속성(functional dependencies) 같은 Haskell의 흔한 확장도 몇 가지 지원합니다.

  6. nextaccountic HN

    정적 타이핑과 타입 추론에 대해 궁금한데요. 추론하지 못하는 코드는 어떻게 되나요? TypeScript처럼 동적 타입이 되나요, 아니면 타입 오류가 나나요?

    타입이 없는 기존 코드와 연동해야 하니, 점진적 타이핑(gradual typing)을 쓰는 게 틀림없겠죠?

  7. reikonomusha HN

    Coalton은 순수한 Coalton 코드의 모든 타입을 추론하고 검사합니다. 동적이거나 타입이 없는 표현식 같은 건 없습니다.

    Coalton의 영역 밖에 있는 코드, 즉 순수 Common Lisp 코드는 명시적인 (LISP ...) 폼[0] 안에서 실행합니다. 이 폼은 사용자가 타입을 주석으로 지정해야 하고, 안에 든 코드가 프로그래머가 지정한 계약을 지키는지 확인하는 동적 타입 검사가 추가됩니다(UNSAFE를 쓰면 제외[1]).

    [0] https://coalton-lang.github.io/manual/operators/lisp/

    [1] https://coalton-lang.github.io/manual/operators/unsafe/

  8. rmunn HN

    https://coalton-lang.github.io/manual/topics/whirlwind-tour/#instance-defaulting 를 제가 제대로 이해했다면(직접 읽어 보세요. 제가 잘못 이해했을 수도 있습니다. 저는 Coalton을 써 본 적은 없고 매뉴얼만 읽었습니다), Coalton은 경우에 따라(숫자가 대표적이지만 숫자만은 아닙니다) 타입을 추측합니다. 추론하지 못한 타입에 대해 경고를 내는지 오류를 내는지는 모르겠지만, Common Lisp를 기반으로 하니 경고를 내고 알 수 없는 타입인 채로 계속 진행하지 않을까 짐작합니다.

    그래도 Coalton이 타입을 알고 있을 때의 이점은 분명합니다. 그래서 (declare foo Integer) 형태가 있는 겁니다. 이건 어떤 코드로도 컴파일되지 않는 컴파일러 힌트로, foo가 float64/double이 아니라 정수라고 가정해도 된다고 Coalton에 알려 줍니다. 그러면 (+ foo 5)에서 어느 구현의 +를 쓸지 컴파일 시점에 고를 수 있습니다.

    Coalton을 소개하는 2025년 영상 https://www.youtube.com/watch?v=of92m4XNgrM 에 타입을 알면 Coalton이 뭘 할 수 있는지 보여 주는 예가 있습니다. 발표자이자 Coalton의 주 개발자인 Robert Smith는 float32, float64, 소수 법(modulo a prime) 정수 등 어떤 숫자 타입으로든 호출할 수 있게 제네릭 숫자 타입을 쓴 고속 푸리에 변환(FFT) 함수를 예로 듭니다. 이걸 벤치마크하면 200만 번 실행하는 데 1초쯤 걸립니다. 그런데 함수 선언 위에 (monomorphize)라는 컴파일러 힌트 하나를 붙이면 Coalton에 이렇게 말하는 셈이 됩니다. "이 함수 안에서 디스패치 테이블을 찾아 매개변수 타입에 따라 서로 다른 + 구현을 호출하지 말고, 함수 복사본을 두 개 만들어. 하나는 특화된 float32 연산 함수를 부르고, 다른 하나는 특화된 float64 연산 함수를 부르게." (소수 법 정수 타입으로도 호출한다면 세 개가 됩니다.) 이러면 디스패치 테이블 조회가 사라지고, 컴파일러가 훨씬 더 특화된 코드를 만들 수 있습니다. 물론 바이너리가 커지는 대가를 치르죠. 속도와 크기를 맞바꾸는 것이라고 그도 분명히 말하고, 그래서 Coalton이 기본으로 하는 게 아니라 (함수 정의 위에 (monomorphize) 선언을 붙여서) 직접 선택하는 방식입니다.

    얘기가 샜네요. 네, 타입을 추론하지 못하는 코드에는 동적 타입을 쓸 거라고 생각합니다(다만 아직 Coalton을 써 보지 않았다는 단서를 붙입니다). 다만 경고도 함께 낼 거라고 꽤 확신합니다. 오류를 낸다면 해결책은 적당한 자리에 (declare [이름] [타입]) 줄을 추가하는 겁니다.

  9. brlewis HN

    기사의 첫 문단을 읽었을 때는 Lisp 사용자가 의존성을 그다지 많이 모으지 않는다는 데 동의했습니다.

    그런데 둘째 문단을 읽고 나니 당신 말에 동의하게 되네요. Lisp는 중요한 생태계 라이브러리 면에서는 잘 지내고 있습니다. 기사는 "자리 잡은 라이브러리는 믿을 수 없을 만큼 안정적이고, 수십만 명의 개발자가 테스트했고, 수천 개의 CI 파이프라인에 들어가 있으며, 해당 분야의 전문가들이 유지보수한다"고 사실인 양 단언하면서 바로 그 점을 전제로 깔고 있습니다.

  10. znpy HN

    저는 그렇게 보이지 않는데요.

    sbcl 자체는 살아 있고 꽤 잘 지내는 건 맞지만, 그것 말고는 풍경이 상당히 암울합니다.

    아이러니하게도 요즘 가장 성공한 Lisp는 Clojure인데, 이건 대체로 JVM에 얹혀 가면서 Java 라이브러리와 프레임워크를 거의 그대로 재사용할 수 있으니까요.

  11. skydhash HN

    Lisp는 표현력이 꽤 높다는 점이 핵심입니다. 기초 라이브러리(대부분 알고리즘)만 몇 개 있으면 나머지는 아주 쉽게 쌓아 올릴 수 있습니다. Python이나 Go 같은 곳에서는 라이브러리 하나로 개념 모델을 정의하고 나면, 그걸 다른 생태계와 이어 줄 글루 코드용 라이브러리가 또 필요합니다. Lisp에서는 거의 모든 것이 기본 list, alist, plist를 씁니다.

    그래서 핵심 로직부터 설계하고, 외부 의존성에는 shim을 써서 맞춥니다. 처음부터 의존성을 끌어오는 게 아니라요.

  12. znpy HN

    기초 라이브러리(대부분 알고리즘)만 몇 개 있으면 나머지는 아주 쉽게 쌓아 올릴 수 있습니다.

    그건 그런데 저는 그러기 싫습니다. 예를 들어 IAM 인증으로 RDS에 접속해야 한다고 해 봅시다.

    그걸 위한 코드를 직접 쓰고 싶지 않고, 라이브러리를 쓰고 싶습니다.

    chicken scheme에서는 되는데 sbcl에서는 안 되고 cmucl에서는 될지도 모르는 라이브러리는 필요 없습니다.

    직접 할 수 있다는 건 압니다. 하기 싫은 겁니다. 다른 사람이 쓰고 유지보수하는 코드를 재사용하고 싶습니다.

  13. skydhash HN

    그걸 위한 코드를 직접 쓰고 싶지 않고, 라이브러리를 쓰고 싶습니다.

    그런 필요가 있었던 사람들은 전부 그걸 위한 코드를 직접 썼습니다. 그리고 그들은 무보수로 제대로 된 라이브러리까지 만들어 줄 생각은 없었겠죠.

    직접 할 수 있다는 건 압니다. 하기 싫은 겁니다. 다른 사람이 쓰고 유지보수하는 코드를 재사용하고 싶습니다.

    그럼 Lisp는 당신에게 맞지 않는 것 같습니다.

  14. znpy HN

    그럼 Lisp는 당신에게 맞지 않는 것 같습니다.

    그리고 다시 원점이네요. 업계 대부분에게 가서 그렇게 말해 보세요. 그게 바로 Lisp의 저주입니다.

    제 말이 맞다는 걸 증명해 주셔서 고맙습니다.

    Lisp 커뮤니티가 이런 엘리트주의 마인드니, "Lisp의 저주"라는 게 있는 것도 당연하죠.

  15. jedberg HN

    정말 맞는 말입니다. 최근에 제가 발견한 버그를 고치려고 에이전트에게 오픈소스 프로젝트의 로컬 복사본을 수정해 달라고 시켰습니다. 에이전트가 버그를 고쳤고, 가끔 공개 저장소에 리베이스도 합니다.

    그런데 왜 패치를 제출하지 않았을까요? 에이전트가 쓴 코드를 제가 검토하지 않았기 때문입니다. 확인도 안 한 패치를 제출하면 마음이 편치 않을 텐데, 확인할 시간은 없고요.

  16. everforward HN

    저도 Clojure로 이걸 해 보고 있는데, 제가 본 가장 큰 함정은 피하게 되더군요. 에이전트가 만드는 인터페이스가 투박하다는 겁니다. 기존 라이브러리를 재사용하면 일단 말이 되는 인터페이스에서 출발하게 되죠.

    참고로 Go에서도 같은 걸 봤습니다.

    코드가 잘 돌아가는 건 분명하고, 그 점을 부정하려는 건 아닙니다. 하지만 지켜보지 않으면 인터페이스가 끔찍해집니다. 제 에이전트는 name 변수를 문자열로 넘기면서, 인자로 받는 구조체 두 개에도 그 name을 따로 넣은 Go 함수를 썼습니다. 내부 함수에서 데이터를 여러 번 다시 검증하는 것도 봤는데, 그러면 모든 함수가 error를 돌려줘야 하죠.

    그리고 LLM만 쓰는 코드라면 별로 중요하지 않은 문제이기도 합니다. 토큰이 좀 더 들겠지만, 손으로 코드를 다듬을 만큼은 아닙니다.

  17. BeetleB HN

    저도 그래요.

    KMyMoney가 (일부) OFX 파일을 가져오지 못하게 됐어요. 그래서 LLM에게 디버깅을 시켰죠.

    정말 파란만장한 여정이었어요. 어떤 QT 라이브러리의 알 수 없는 버그였는데, 2019년에 잠깐 설치했다가 몇 년 전에 지운 전혀 무관해 보이는 것 때문에 발동한 거였어요.

    2019년의 잔재를 청소하는 것으로 문제를 해결하긴 했지만, QT 버그는 여전히 남아 있어요. LLM에게 정리 글도 쓰게 했지만 제출할 일은 없을 거예요. 꽤 복잡한 내용이고 저는 QT 코드를 전혀 모르거든요.

  18. fc417fc802 HN

    최소 재현 코드를 만들 수 있었다면 그건 제출해 주셨으면 좋겠습니다. 슬롭(slop)으로 가득 찬 커밋을 담장 너머로 던지는 건 물론 못된 짓이지만, 의존성이 거의 없고 버그를 확실하게 재현하는 작은 스크립트를 던지는 건 거의 틀림없이 도움이 됩니다. 실제로 문제를 어떻게 풀지는 전문가들에게 맡기면 되고요.

  19. BeetleB HN

    저는 버그를 고친 적이 없어요. 버그를 일으킨 것을 그냥 치웠을 뿐이죠.

    재현 코드 같은 건 있는 것 같지만, 그 스크립트조차 아마 이해하지 못할 거예요. 누가 버그를 제보하면서 "이 스크립트로 재현됩니다"라고 해 놓고 정작 본인은 그 스크립트가 뭘 하는지 모른다면, 좋게 받아들여지지 않을 것 같아요.

  20. fc417fc802 HN

    그 논리는 "기여"에나 해당됩니다. 문서화도 안 된 코드인데 내가 정의를 대충 해 놓은 문제를 고치는 것 같고, 어떻게 동작하는지는 나도 모르니 머지해 달라는 식이죠.

    버그 리포트에서는 (적어도 제 생각엔) 군더더기 없이 오류를 확실하게 재현하는 최소 예제가 기본 구성 요소입니다. 제보자가 왜 되는지 이해할 필요는 없고, 설명을 내놓을 필요는 더더욱 없습니다. 오히려 복잡한 프로젝트에서는 제보자가 내놓은 설명이 미묘하게 틀려서 오해를 부르는 경우가 태반입니다. 버그에 대한 추가 "문서화"가 있다면 오히려 달갑지 않습니다. 결함을 명백하게 보여 주고 빠지세요.

  21. BeetleB HN

    제 말은, 돌아오는 답이 "이 스크립트는 말도 안 되고 당연히 실패해야 한다"일 수도 있다는 거예요.

    그러면 저는 누군가의 시간을 낭비한 셈이 되고요.

    언젠가 제 블로그에 정리 글을 올릴 것 같기는 해요.

  22. fc417fc802 HN

    라이브러리를 거의 이해할 수 없고 명백히 의도하지 않은 방식으로 쓰다가 엣지 케이스에 부딪혔다면, 보고하는 게 도움이 안 될 수도 있겠죠. 하지만 말씀하신 사용 방식(폐기한 설치본에서 남은 오래된 설정이나 캐시 데이터를 만나는 경우)은 비록 드문 일이긴 해도 의도하지 않은 사용이라고 하기 어렵습니다.

    최종 사용자가 "예상되는 사용" 범위 안에서 오류를 만났다면 그 버그는 틀림없이 유효합니다. 다만 그게 실제로 누구의 버그인지(라이브러리가 고장 난 건지, 그 라이브러리를 쓰는 프로그램이 잘못 쓴 건지)는 꼭 알 수 있는 건 아니죠.

  23. CyberDildonics HN

    관련된 사람에게 필요한지 물어보거나, 그 코드를 만든 프롬프트를 알려 주면 안 되나요? 확인하고 다듬는 수고를 들이는 사람이 공을 가져가도 되잖아요.

  24. cmrdporcupine HN

    프로젝트마다 다르지만, 어떤 곳은 이런 걸 대놓고 적대적으로 받아들여요. 정당할 때도 있고, 아닐 때도 있고요.

    솔직히 그럴 가치가 없어요. 양쪽 입장이 다 이해되지만, 사람들이 새로운 협업 방식을 찾아내야 할 거예요. 풀 리퀘스트는 아마 이제 답이 아닐 거예요.

  25. cestith HN

    이 "저주"는 Lisp에만 있는 게 아닙니다. 오래된 말 중에, Forth를 설치하고 첫 주까지는 모두와 같은 Forth를 쓰지만 그 뒤로는 자기만의 Forth 방언이 생긴다는 취지의 말이 있습니다.

    새 문법을 만드는 데 강력하면서 그에 걸맞게 강력한 커뮤니티 저장소는 없는 언어라면 어디서든 어느 정도는 같은 효과가 나타납니다.

  26. gavinray HN

    저도 2월에 같은 우려를 글로 썼습니다. 성숙한 라이브러리를 검색 한 번으로 찾는 것보다 맞춤 소프트웨어를 만드는 게 더 쉬워지면 어떻게 될까요?

    https://gavinray97.github.io/blog/llm-build-cheaper-than-searching

  27. xscott HN

    긍정적인 결과 하나는 취약점이 훨씬 다양해진다는 겁니다. 부정적으로 들리겠지만 그렇지 않아요.

    예를 들어 블랙햇 해커가 PHP의 버그 하나로 웹사이트의 70%를 손에 넣을 수 없게 됩니다. 특정 사이트를 하나하나 노려야 하고, 그 익스플로잇이 다른 곳에서 통할 가능성은 별로 없으니까요.

  28. andai HN

    무슨 말인지 모르겠는데요. 이 시나리오에서는 (PHP 인터프리터에 해당하는 것)도 바이브 코딩으로 만든다는 건가요?

  29. AirMax98 HN

    윗분께는 left-pad가 더 나은 비교 대상일 것 같아요.

  30. dcss_gardener HN

    저는 알려진 취약점이나 일부러 심어 둔 취약점이 있는 여러 서버 스택을 LLM으로 레드팀 테스트해 보면서 얼마나 피해를 줄 수 있는지 살펴보고 있습니다.

    수익이 될 만한 성과를 전혀 못 내는 경우는 유니커널(unikernel) 웹앱 하나뿐이었습니다. 소스도 셸도 없으니 취약점은 찾아내도 그걸로 할 수 있는 최악이 기껏해야 데이터를 한 번 오염시키거나 빼내거나 서버를 죽이는 정도입니다. 그마저도 못 알아내는 경우가 많고, 나중에 다시 들어올 안정적인 통로조차 남기지 못합니다.

    물론 유니커널의 전통적인 문제는 필요한 걸 전부 직접 포팅해야 한다는 겁니다. 하지만 그게 싸졌다는 게 바로 지금 우리가 얘기하는 거죠.

    보안은 모호함에서 나온다는 말이 다시 메뉴에 올라온 모양입니다.

Hacker News에서 보기 ↗