# 코드는 가장 엄밀한 명세다 코딩 에이전트가 자연어 프롬프트를 입력으로 받아 즉시 실행 가능한 소프트웨어를 출력하는 함수라고 상상해보자. 실제로 바이브 코딩은 이러한 가정 위에 세워진 프로그래밍 방식이다. 바이브 코딩으로 작성된 코드는 철저히 블랙박스로 취급된다. 개발자는 더 이상 어려운 프로그래밍 언어를 배우지 않고도 원하는 동작을 수행하는 소프트웨어를 만들어 낼 수 있다. 그렇다면 인간이 프로그래밍 언어의 규칙을 따라 작성한 코드, 더 나아가 [[artificial-intelligence]]이 자연어 프롬프트를 입력받아 생성하는 코드조차 결국에는 불필요해질까? 코드는 소프트웨어의 동작을 정의하는 명세 그 자체다. 소프트웨어를 자연어가 아니라 프로그래밍 언어로 작성하는 이유가 단순히 기계어와 자연어 사이를 매개하기 위해 어쩔 수 없이 거쳐야는 레이어가 있기 때문만은 아니다. 명세를 가장 엄밀하게 정의할 수 있는 수단이 코드이기 때문에 소프트웨어를 코드로 작성하는 것이다. 자연어를 이용해 소프트웨어의 명세를 정의하는 것이 불가능하지는 않다. "A를 누르면 X를 하고, B를 누르면 Y를 한다"라는 명세로 만들어진 프로그램은 아마 의도한대로 잘 동작할 것이다. 그러나 명세가 복잡해지면 자연어로 작성된 명세 문서는 그 이상으로 복잡해진다: "A를 누르면 X를 하되, C가 활성화되어 있다면 X'을 한다. B를 누르면 Y를 하되, C가 활성화되어 있다면 Y'을 한다. 이때 A와 B를 동시에 누르면 Z를 하되, C가 활성화되어 있다면 아무런 동작을 하지 않는다." 이런 식으로 소프트웨어의 동작을 바탕으로 엣지 케이스를 하나씩 대응하며 문서를 보완하다보면 새로운 프로그래밍 언어를 배우는 것보다 명세 문서에 쓰인 글을 해석하는 것이 더 어려워질 것이다. 복잡한 명세의 실증적인 예시로는 상속법 법령이 있다. 보다시피 법령은 자연어로 쓰여있지만, 다양한 조건과 예외에 따른 우선순위, 상속분을 해석하려면 코드를 읽는 것 이상으로 많은 노력이 필요하다. > [[civil-law]] 제1000조(상속의 순위) > > - (1) 상속에 있어서는 다음 순위로 상속인이 된다. > 1. 피상속인의 직계비속 > 2. 피상속인의 직계존속 > 3. 피상속인의 형제자매 > 4. 피상속인의 4촌이내의 방계혈족 > - (2) 전항의 경우에 동순위의 상속인이 수인인 때에는 최근친을 선순위로 하고 동친등의 상속인이 수인인 때에는 공동상속인이 된다. > - (3) 태아는 상속순위에 관하여는 이미 출생한 것으로 본다. > [[civil-law]] 제1003조(배우자의 상속순위) > > - (1) 피상속인의 배우자는 제1000조 제1항 제1호와 제2호의 규정에 의한 상속인이 있는 경우에는 그 상속인과 동순위로 공동상속이 되고 그 상속인이 없는 때에는 단독상속인이 된다. > - (2) 제1001조의 경우에 상속개시전에 사망 또는 결격된 자의 배우자는 동조의 규정에 의한 상속인과 동순위로 공동상속인이 되고 그 상속인이 없는 때에는 단독상속인이 된다. > [[civil-law]] 제1008조의2(기여분) (1) 공동상속인중에 상당한 기간 동거·간호 그 밖의 방법으로 피상속인을 특별히 부양하거나 피상속인의 재산의 유지 또는 증가에 특별히 기여한 자가 있을 때에는 상속개시 당시의 피상속인의 재산가액에서 공동상속인의 협의로 정한 그 자의 기여분을 공제한 것을 상속재산으로 보고 제1009조 및 제1010조에 의하여 산정한 상속분에 기여분을 가산한 액으로써 그 자의 상속분으로 한다. > [[civil-law]] 제1009조(법정상속분) > > - (1) 동순위의 상속인이 수인인 때에는 그 상속분은 균분으로 한다. > - (2) 피상속인의 배우자의 상속분은 직계비속과 공동으로 상속하는 때에는 직계비속의 상속분의 5할을 가산하고, 직계존속과 공동으로 상속하는 때에는 직계존속의 상속분의 5할을 가산한다. > [[civil-law]] 제1112조(유류분의 권리자와 유류분) 상속인의 유류분은 다음 각호에 의한다. > > 1. 피상속인의 직계비속은 그 법정상속분의 2분의 1 > 2. 피상속인의 배우자는 그 법정상속분의 2분의 1 > 3. 피상속인의 직계존속은 그 법정상속분의 3분의 1 > 4. 피상속인의 형제자매는 그 법정상속분의 3분의 1 별거 중인 배우자와 두 명의 자식이 있는 상속인이 45억원을 유산으로 남겼는데, 30억을 사회에 기부하겠다고 유언했고, 이웃에게 5억의 채무가 있으며, 상속인을 간병해온 딸이 생전에 농지를 구입하는데 실질적 자금을 제공하여 그 가치액이 현재 5억원이라면, 두 직계비속과 배우자가 얼마의 법정상속분을 갖고, 얼마의 유류분을 인정받을 수 있을지 계산해보자. 이 정도로 복잡한 명세라면 if 구문이 여러 겹으로 중첩된 코드라도 동원해 명세를 정의하는 것이 나을 법하다. 복잡한 명세를 정의해야 하는 법령은 자연어가 쉽다는 주장이 무색하게 일관된 규칙과 형식을 제약한다. 프로그래밍 언어가 하는 바로 그것이다. ```ocaml let 상속계산 ~적극재산 ~유증액 ~채무 ~전체상속인후보 = let 배우자목록 = List.filter (fun 사람 -> 사람.배우자여부) 전체상속인후보 in let 혈족목록 = List.filter (fun 사람 -> not 사람.배우자여부) 전체상속인후보 in let 최선순위지위 = List.find (fun 순위 -> List.exists (fun 사람 -> 사람.지위 = 순위) 혈족목록) [직계비속; 직계존속; 형제자매; 방계혈족] in let 최선순위혈족 = List.filter (fun 사람 -> 사람.지위 = 최선순위지위) 혈족목록 in let 공동상속인목록 = 배우자목록 @ 최선순위혈족 in let 배우자가산대상지위 = 최선순위지위 = 직계비속 || 최선순위지위 = 직계존속 in let 지분점수 사람 = if 사람.배우자여부 && 배우자가산대상지위 then 1.5 else 1.0 in let 총지분점수 = List.fold_left (fun 누적 사람 -> 누적 +. 지분점수 사람) 0.0 공동상속인목록 in let 법정상속분비율 사람 = 지분점수 사람 /. 총지분점수 in let 유류분비율 사람 = match 사람 with | { 배우자여부 = true; _ } -> 1.0 /. 2.0 | { 지위 = 직계비속; _ } -> 1.0 /. 2.0 | { 지위 = 직계존속; _ } -> 1.0 /. 3.0 | { 지위 = 형제자매; _ } -> 1.0 /. 3.0 | _ -> 0.0 in let 실제분배대상 = 적극재산 -. 채무 -. 유증액 in let 유류분기초재산 = 적극재산 +. List.fold_left (fun 누적 사람 -> 누적 +. 사람.생전증여) 0.0 전체상속인후보 -. 채무 in let 법정상속분금액 사람 = 법정상속분비율 사람 *. 실제분배대상 in let 유류분금액 사람 = 유류분비율 사람 *. 법정상속분비율 사람 *. 유류분기초재산 in let 유류분부족액금액 사람 = let 차액 = 유류분금액 사람 -. 사람.생전증여 -. 법정상속분금액 사람 in if 차액 > 0.0 then 차액 else 0.0 in List.map (fun 사람 -> { 상속인이름 = 사람.이름; 법정상속분 = 법정상속분금액 사람; 유류분 = 유류분금액 사람; 유류분부족액 = 유류분부족액금액 사람; }) 공동상속인목록 ``` 유연함은 자연어의 장점이자 단점이다. 일상 대화와 학습에 있어 자연어가 유연하다는 점은 장점이다. 그러나 자연어는 너무 유연하기 때문에 같은 명세도 다양한 문장으로 표현할 수 있고, 같은 문장도 다양한 명세로 해석될 수 있다. 명세가 복잡해질수록 그 다양성은 기하급수적으로 증가해 명세로 유도할 수 있는 결과물인 소프트웨어의 일관성을 보장할 수 없게 된다. 한편 프로그래밍 언어에는 명확한 제약이 있다. 제약이 강한 언어일수록 같은 명세를 구현했을 때 서로 유사한 코드가 유도된다. 같은 텍스트가 같은 명세의 구현을 보장한다는 점은 우리가 코드라고 부르는 텍스트가 가진 특성이다. 이러한 코드의 특성과 그 장점으로 인해 인공지능의 소프트웨어 저작 능력이 탁월하게 발전해도 코드는 여전히 쓰이고, 읽힐 것이다. 수학적 논리 구조를 자연어로 표현할 수 있음에도 수식을 사용하는 것과 마찬가지다. ## 관련문서 - [[surviving-in-ai-era]] - [[software-engineer-in-ai-era]] - [[software-development-as-engineering]] - [[google-prompt-engineering]]