개발자 다 망했다(?)

KO EN
2025년 10월 23일 · 22분 읽기 · 조회 83 · 💬 0

AI 딸깍이라는 말이 있다.

사람이 며칠 걸려 짜던 코드를 AI는 몇 초 만에 뚝딱 만들어낸다.

실제로 AI 툴에게 로그인 기능 만들어줘라고 하면 그럴듯한 코드가 나온다.

이 버그 고쳐줘라고 하면 순식간에 해결책을 제시한다.

그렇다면 개발자는 곧 사라질까?

나는 이 질문이 불안했다.

개발자란 무엇을 하는 사람인가?


내 생각에 개발자는

멋들어지는 깔끔한 코드로 최신 트렌드를 주도하며

훌륭한 소프트웨어를 만드는

그런 사람이 아니다.

개발자는 프로그램을 만드는 사람이다.

프로그램이란 무엇이냐?

어떠한 번거로운 일을 자동화 하여 수행할 수 있는 무언가이다.

사전은 이렇게 정의한다.

어떤 문제를 해결하기 위하여 그 처리 방법과 순서를 기술하여

컴퓨터에 주어지는 일련의 명령문 집합체.

프로그램을 만든다는 건 문제를 해결한다는 것이다.

즉, 개발자는 문제를 푸는 사람이다.

그렇다면 ‘문제’란 무엇일까?

이 세상에는 수많은 문제가 존재한다.

예를 들어, 배고픔을 해결하는 문제를 생각해보자.

취할 수 있는 행동은 다양하다.

빵을 먹는다, 밥을 먹는다, 배달을 시킨다... 등

무수히 많은 선택지가 존재한다.

각 행동에는 그에 따른 결과가 수반된다.

밥을 먹는다 라는 것도

밥을 1공기 먹는다,

밥을 한숟가락 먹는다...

등등 선택지가 다양하다.

그렇다면 그 선택으로 인해 어떻게 되는가?

밥을 먹으면 무조건 배부른 것이 아니듯,

우리가 취하는 행동이 무조건 문제를 해결하는 것은 아니며,

적절한 선택을 해야 원하는 결과를 얻을 수 있다.

"이러이러한 입력을 넣으면, 이러이러한 결과를 얻는다."

라는 대응 관계로 표현될 수 있는 것이 바로 문제(Problem)다.

중학교 수학에서 배우는 '집합(Set)' 개념으로 표현해보면

빵을 먹는다 -> 배고픔이 해결된다.

빵을 먹는다 -> 배고픔이 해결되지 않는다.

와 같은 관계 쌍으로 만들 수 있다.

이처럼 문제는 선택과 결과 사이의 관계쌍으로 정의할 수 있다.

즉 문제(Problem )란, 어떠한 입력군(Inputs )과 출력군(Solutions ) 사이의 관계로 정의할 수 있다.

우리가 흔히 문제를 푼다고 말할 때,

사실 그것은 입력 I와 출력 S 사이의 대응 관계를 찾아내는 일이다.

이를 수학적으로 표현하면,

문제는 다음과 같은 이항관계(binary relation) 로 나타낼 수 있다.

$P\ ⊆\ I\times S\ \ \ \ |\ \ \ \ (i,\ s)\ ∈\ P$

여기서 P 는 가능한 입력과 출력 중 실제로 ‘의미 있는’ 조합만을 포함한다.

즉, 입력 i 가 출력 s 에 대응된다는 뜻이며 이 기표에 함의된 의미는,

선택과 그 결과가 의미 있게 연결되는 경우만을 '문제'라고 보겠다는 뜻이다.


그런데 위의 예시처럼 입력군과 출력군의 차원이 지나치게 많아지면,

관계의 구조를 파악하기가 어렵다.

우리는 이러한 복잡도를 낮추고 논의를 더 엄밀히 하기 위해,

출력군을 단순화하여 다음과 같이 정의하기로 한다.

S := { true, false }

이는 일종의 통제변인(control variable) 설정과 같다.

이제 우리는 모든 문제를 “입력에 대하여 참인지 거짓인지 판단하는 문제”로 한정할 수 있다.

즉, “주어진 입력이 어떤 조건을 만족하는가?”를 판별하는 것이다.

이러한 문제를 결정 문제(Decision Problem) 라고 부른다.

$f\ :\ I\ →\ \left\{0,1\right\}$

이 관계를 통해 정의역과 치역을 가지는 함수쌍으로 표현할 수 있게 되었다.

이는 앞서 정의한 일반적인 문제 개념과 동일한 구조를 가지되,

출력의 차원을 ‘참/거짓’으로 축소함으로써

문제를 보다 단순하고 수학적으로 다루기 쉽게 만든 형태다.

이렇게 문제를 형식화 했다.

그렇다면, 왜, 굳이,

이렇게 도식화 하였을까?


수학자 앨런 튜링은 이러한 질문을 했다.

문제를 푸는 존재가 있다면, 그는 어떤 방식으로 사고하고 계산할 수 있을까?

이 질문에 답하기 위해, ‘계산(Computation)’이란 개념 자체를 완전히 재정의했다.

사람들이 수학 문제 해결하는 것에 집중할 때

튜링은 문제를 푸는 '행위'에 집중하여

새로운 메타를 제시한 것이다.

다시말해, ‘생각하는 존재가 계산하는 행위' 자체를 모델링하려 했다는 뜻이다.

그는 한 사람의 수학자가 종이에 기호를 적으며

순차적으로 규칙을 적용하는 과정을 관찰하고,

그 행동을 기계적으로 표현할 수 있다고 가정했다.

그렇게 등장한 것이 바로 튜링머신(Turing Machine)이다.

튜링은 인간의 계산 행위를 구성하는 가장 단순한 요소를 세 가지로 분해했다.

  1. 테이프(Tape): 일정한 크기의 셀(Cell)로 나뉘어 있는 종이테이프. 각 셀에는 기호가 기록되어 있으며 길이는 무한히 늘어날 수 있다.

  2. 헤드(Head) : 종이테이프의 특정 한 셀을 읽을 수 있는 헤드. 이동이 가능하다. 또는 헤드는 고정되어 있고 테이프가 이동한다.

  3. 상태 기록기(State register) : 현재 튜링 머신의 상태를 기록하고 있는 장치.

기계는 테이프의 한 칸(셀)을 읽고,

규칙에 따라 새로운 기호를 쓰거나 왼쪽 또는 오른쪽으로 한 칸 이동한다.

놀랍게도 이 단순한 과정을 반복하는 것만으로, 우리가 상상할 수 있는 거의 모든 계산을 표현할 수 있다.

튜링은 바로 이 세가지 요소만으로 구성된 단순한 기계로

현대의 모든 컴퓨터가 수행할 수 있는 계산의 본질을 증명했다.

만약 어떤 문제의 해답을,

튜링머신이 유한한 시간 안에 계산할 수 있다면,

그 문제는 계산 가능(Computable)한 것으로 보았다.

즉, 계산 가능하다는 것은 그 문제를 명확한 절차(Algorithm) 로 풀 수 있다는 뜻이다.

튜링의 이러한 증명덕분에 불행스럽게도

오늘날 우리는 코딩이라는 노동을 하고있게 되었다.


앞서 튜링머신은 거의 모든 계산을 표현할 수 있다고 했다.

"거의" 모든? 왜 튜링은 거의 모든 이라고 했을까?

아무리 빠른 알고리즘을 짜고,

아무리 효율을 높인다 해도

애초에 풀 수 없는 문제가 존재한다면?

튜링은 이 질문에서 출발했다.

주어진 프로그램과 입력이 있을 때, 이 프로그램이 언젠가 멈출까? 아니면 영원히 실행될까

이게 바로 정지 문제(Halting Problem)라 부르는 것이다.

얼핏 보기엔 단순하다. 하지만 단순하지 않다

단순히 멈춘다, 멈추지 않는다 라고 자명하게 답하기 어려운 문제다.

하지만 튜링은 놀라운 결론을 내린다.

그 어떤 알고리즘도, 모든 프로그램의 정지 여부를 판별할 수는 없다.

예/아니오가 아닌 애초에 문제 자체를 뛰어넘은 결론이다.

튜링은 이러한 가정을 했다.

모든 프로그램의 정지 여부를 판단하는 완벽한 ‘정지 여부 판별기’가 존재한다고 치고,

이제 그 판별기를 입력으로 사용하는 새로운 프로그램을 하나 만든다.

이 프로그램은 판별기의 결과를 거꾸로 행동하도록 설계한다.

입력값이 ‘멈춘다’고 판단하면, 계속 실행하고

입력값이 ‘멈추지 않는다’고 판단하면, 즉시 멈추겠다.

# 가정: 완벽한 정지 판별기 H(program, input)
# H(program, input) → True  : program이 멈춘다
# H(program, input) → False : program이 멈추지 않는다

def HaltingParadox(program):
    if H(program, program) == True:
        while True: pass   # 무한 루프
    else:
        return "멈춰"

그런데 이 프로그램이 자기 자신을 입력으로 받는 순간,

이상한 일이 벌어진다.

HaltingParadox(HaltingParadox)

“멈춘다”고 예측하면 계속 돌아야 하고,

“멈추지 않는다”고 예측하면 즉시 멈춰버린다.

어떤 판단을 내려도, 결과는 모순이다.

따라서 ‘정지 여부 판별기’가 존재한다는 가정 자체가 성립할 수 없다.

"나는 거짓말쟁이다" ← 이 문장이 참인가 거짓인가?

이렇듯 튜링의 증명 방식은 역설에 가깝다.

단순하지만, 피할 수 없는 자기모순의 함정 속에서

계산 가능한 것과 계산 불가능한 것을 가르는 경계를 드러냈다.

이 단순한 역설을 통해 계산의 절대적인 한계를 보였고,

모든 문제가 Computable한 것은 아니라는 결론을 내렸다.

이것이 바로 계산 불가능성(Non-computability) 이다.

튜링의 정지 문제는 계산할 수 없는 것,

즉 아무리 뛰어난 알고리즘으로도 도달할 수 없는 한계선을 보여주었다.

이러한 증명은,

비록 모든 문제를 해결할 수는 없겠지만

그래도 거의 모든 문제를 해결 할 수 있는 모델을

수학적으로 정의한 결과이다.

위의 역설을 통해 Computable의 상한을 발견하였다고 하더라도

모든 문제가 계산 불가능 한 것은 아니다.

대부분의 문제들은 시간과 알고리즘만 있다면

튜링머신으로 충분히 해결 가능한 세계에 속한다.


그러나 계산이 가능하다는 말은,

언제나 가능한 시간 안에 풀린다는 뜻은 아니었다.

어떤 문제는 금세 답을 내지만,

어떤 문제는 상상할 수 없을 만큼 느리다.

입력이 커질수록 계산에 걸리는 시간이 얼마나 늘어나는지를

‘시간 복잡도(Time Complexity)’라고 부르며 O(n) 처럼 표현한다.

현대의 사람들은 프로그램의 작동여부보다,

얼마나 빠르고 효율적으로 동작하느냐를 더 중요하게 생각한다.

실행되지 않는 프로그램보다 느리게 동작하는 프로그램에 더 분노하지 않던가

게임만 해도, 이러한 시간복잡도가 굉장히 중요하다.

리뷰에서 가장 많이 발견하게 되는 키워드는 아마 "최적화" 일것이다.

게임이 돌아가기만 하면 끝이 아니라,

느리지 않고, 부드럽게, "잘"

작동해야 되는게 이 바닥의 규칙이다.

그래서 나같은 힘없는 개발자들에게 중요한 건

동작하는 프로그램을 만드는 것이 아니라

더 효율적이고, 더 효과적인 프로그램을 만드는 것이다.


어느 날, 마을의 이장님이 동네의 젊은이들을 불러 다음과 같은 문제를 냈다.

방안에 100개의 공이 있다.

크기는 모두 같지만, 단 하나의 '가짜 공'만 재질이 달라 무겁다.

이 공 중에서 '가짜 공'을 찾으라.

이 문제는 불가능한 문제처럼 보이지 않는다.

시간이 좀 걸릴 뿐, 적절한 방법을 선택하면 누구든 답을 얻을 수 있다.

이장님이 가만히 보니,

젊은이들은 저마다 다른 방식으로 문제를 풀고 있었다.

  1. 시간 빌게이츠 유형

모든 공의 무게를 하나씩 재고, 가장 무거운 공을 고른다.

100번의 compute가 필요하지만 확실한 방법이다.

아주 정직한 청년들로, 마을의 훌륭한 역군이 될 것이다.

  1. 그들만의 리그 유형

공을 절반씩 나누어 양팔 저울에 올린 뒤,

무거운 쪽만 남기고 다시 절반으로 나눈다.

이 과정을 반복하면 대략 log₂100 ≈ 7번의 compute로 답을 찾을 수 있다.

효율적이다.

  1. 구글 입사문제 유형

경사면 위에 모든 공을 배치해서

동시에 굴렸을 때 가장 먼저 도착하는 공을 찾는다.

compute는 단 한번만 필요하다.

평소 인터넷에 올라오는 구글 입사문제를 즐겨푸는 사람들로, 얼핏 천재처럼 보인다.

(그렇지만 정작 구글에 들어갔다는 소식은 들은 바 없다.)

이 세 가지 방식은 모두 문제를 다항시간(Polynomial time) 안에 해결할 수 있는 절차를 갖는다.

즉, 주어진 입력에 대해 정답을 직접 계산(Compute) 할 수 있으며,

그 계산 과정이 입력 크기에 비례해 예측 가능한 시간 안에 끝난다.

조금 더 전문적으로 표현하자면,

탐색(Search) 과 검증(Verification) 이 모두 다항시간 안에 수행 가능한 문제들이다.

이러한 성질을 가진 문제의 집합을 P(Polynomial time solvable) 문제라고 정의한다.


이장님은 젊은이들이 가져온 공을

저울에 한 번만 올려보아도 그 말이 맞는지 즉시 확인할 수 있다.

정답을 찾는 과정에 비해, 검증은 매우 간단하다.

여기서 '검증'이라는 것에 대해 잠시 집중해보자.

이런 짓을 해서는 안되겠지만, 모르는 사람의 통장을 주웠다고 하자.

ATM 기계에 입력한 통장 비밀번호가 맞는지 틀린지 확인하는 것은 쉽지만,

이 통장의 비밀번호를 찾는 것은 매우 어렵다.

조금 더 전문적으로 표현하자면,

검증(Verification)은 다항시간(Polynomial time) 안에 가능하지만,

탐색(Search)은 그보다 훨씬 더 복잡할 수 있다는 뜻이다.

이렇듯 정답을 검증하는 것은 빠르지만,

정답을 찾는 과정은 훨씬 더 복잡한 문제들이 있다.

이러한 문제들은 검증 가능한 어려움을 가지며,

이를 NP(Non-deterministic Polynomial time) 문제라고 부른다.


이제 우리는 앞서 말한 문제(Problem)를 드디어

P 문제와 NP 문제로 나누어 말할 수 있다.

얼핏 보면 두 부류의 문제는 명확히 다른 것처럼 보인다.

그러나 자세히 들여다보면, 묘하게 닮아 있다.

P 문제는 정답을 빠르게 찾을 수 있는 문제고,

NP 문제는 정답이 주어지면 빠르게 검증할 수 있는 문제다.

둘 다 결국 다항시간(polynomial time) 안에서 무언가를 해낼 수 있다는 점에서 닮았다.

다만 하나는 해를 직접 계산하는 능력이고,

다른 하나는 이미 주어진 해의 옳음을 판단하는 능력이다.

그렇다면 이 둘은 정말로 다른 존재일까?

만약 어떤 문제의 정답을 빠르게 검증할 수 있다면,

그 정답을 빠르게 찾는 방법도 언젠가 존재하지 않을까?

이 단순하지만 근본적인 의문이 바로

P vs NP 문제로 이어진다.

생각해보면, 이것은 인간의 사고 과정과 닮아 있다.

우리는 무언가를 생각해내는 데에는 시간이 오래 걸리지만,

남이 생각해낸 답이 옳은지는 비교적 빠르게 판단한다.

즉, 창조는 어렵지만 비평은 쉽다.

만들어내는 것은 NP적이고, 평가하는 것은 P적이다.

이는 단순히 수학의 이야기가 아니다.

인공지능이 예술을 창작할 수 있는가?

인간의 창의성은 계산으로 환원 가능한가?

이 모든 질문은 P vs NP의 그림자 아래 있다.

현대 암호는 NP-난해(NP-hard) 문제 위에 서 있다.

검증은 빠르지만 해독은 비현실적으로 느린 구조다.

RSA, 블록체인, 전자서명 모두 마찬가지다.

만약 P = NP라면,

세상의 모든 비밀은 사라질 것이다.

암호는 단숨에 풀리고, 보안은 무너지고,

예술의 창의성마저 AI 딸깍이라는 말처럼 공식으로 환원할 수 있을 것이다.

반대로 P ≠ NP라면,

세상은 조금 불완전하지만 나름 아름답다.

풀 수 없기 때문에, 사람들은 답을 찾기 위해 애쓸 것이다.

그렇기에 이 질문 ─

"P 집합과 NP 집합이 상등인가?"

은 클레이 수학연구소가 밀레니엄 난제(Millennium Prize Problem) 로 선정했다.

명확한 증명을 제시하는 자에게는 100만 달러의 상금이 약속되어 있다.

그러나 지난 수십 년 동안,

누구도 그 증명을 완성하지 못했다.

또한 AI 딸깍으로도 해결 못했다.

이 둘이 같은지, 같지 않은지 자체가 불가지 영역이다.


각설.

AI는 인간이 만든 어떤 기계보다도 빠르게 문제를 푸는 존재다.

무수한 입력을 받아, 단 몇 초 만에 정답을 내놓는다.

놀랍도록 정확하고, 때로는 인간보다 더 창의적으로 보이기도 한다.

AI 딸깍이라는 말이 괜히 나왔을까

하지만 그 창의성조차 사실은 예측 가능한 경로 위에서 작동한다.

AI는 수많은 가능성의 그래프 위를 달리며

각 지점마다 가장 높은 점수를 가진 경로를 선택한다.

바둑이 그랬다.

정복 불가능해 보였던 바둑의 세계도,

알파고는 모든 수를 계산한 것이 아니라

가장 승률이 높은 다음 수를 찾아냈다.

그것은 모든 해를 탐색한 결과가 아니라,

통계적으로 가장 그럴듯한 해를 선택한 결과였다.

ChatGPT도 마찬가지다.

무한한 문장 그래프 위에서

다음 단어의 확률을 계산하고

그중 가장 높은 확률의 단어를 택한다.

예를 들어,

"나는 배고파서"라는 문장이 주어지면

AI는 그 다음에 올 단어를 검색한다.

가령, [ 나는 - 배고파서 - 라면을 - 먹는다 ] 라고 한다면

가장 많이 사용된 조합이기에 확률이 높다.

반면, [ 나는 - 배고파서 - 창문을 - 닫는다 ] 라고 한다면

이 문장은 사용 빈도가 낮아 확률이 낮을뿐,

의미적으로 틀렸다고 판단되는 것은 아니다.

우리는 두 문장을 들으면

직관적으로 참소리인지 헛소리인지 구분을 하지만

AI는 다르다. 어디까지나 확률 계산의 결과다.

마치 길을 따라가는 알고리즘처럼.

이 모든 것은 결국 P 문제의 세계에서 이루어진다.

우리 집에서 서울로 가는 가장 빠른 길을 묻는다면,

AI가 누구보다 빠르게 찾을 것이다.

하지만 그 길의 의미는 모른다.

그저 주어진 조건 안에서

가장 빠르고 효율적인 경로를 찾을 뿐이다.

이유도, 의미도 없다.

AI는 빠르게 계산하고, 빠르게 결정한다.

그러나 그뿐이다.

알파고에게 왜 이 수를 두었는지 묻는다면,

"승률이 가장 높기 때문", 그 이상은 없다.

바둑에 그냥이란 건 없어. 어떤 수를 두고자 할 때는 그 수로 무엇을 하고자 하는 생각이나 계획이 있어야 해. 그걸 '의도'라고 하지.

또 내가 무얼 하려고 할 때는 상대가 어떤 생각과 계획을 갖고 있는지 파악해야 해. 그걸 상대의 '의중'을 읽는다라고 해.

왜 그 수를 거기에 뒀는지 말할 수 있다는 건 결국 네가 상대를 어떻게 파악했는지, 형세를 분석한 너의 안목이 어떠했는지를 알게 된다는 뜻이야.

그냥 두는 수라는 건 '우연'하게 둔 수인데 그래서는 이겨도 져도 배울 게 없어진단다. '우연'은 기대하는 게 아니라 준비가 끝난 사람에게 오는 선물 같은 거니까.

— 미생 中

하지만 NP-hard문제,

즉 정답이 존재하는지조차 효율적으로 알 수 없는 세계에서는

AI도 여전히 인간과 함께 멈춰 선다.

우리가 흔히 말하는 ‘AI 만능주의’는

이 경계 위에서 만들어진 환상같다는 생각이 든다.

AI는 문제를 풀어주는 도구일 수는 있지만,

문제의 의미를 찾는 존재는 아니다.

가장 효율적인 경로를 찾을뿐,

그 길이 어떠한 의미를 가지는지 스스로는 알 수 없다.

그건 여전히 인간의 영역이다.

그래서 P vs NP의 질문은

요즘같은 AI 시대에 더욱 근본적인 질문이 아닐까

AI가 모든 문제를 풀 수 있다고 믿는 순간,

우리가 던져야 할 질문마저 계산하려 할 것이다.

그 불확실성과 창의성, 그리고 모순의 세계

그곳에는 아직 인간이 서 있다.

모든 검증 가능한 것이 반드시 해결 가능한 것은 아니고

모든 계산 가능한 것이 반드시 이해 가능한 것도 아니다.

아마도 이 불완전함 덕분에

우리는 여전히 생각할 수 있는 존재로 남아 있는지도 모른다.

아직 밥벌이는 할 수 있을지도 모른다.

#개발자#앨런튜링#튜링머신#프로그래머#AI#AI일자리대체#PvsNP

댓글 0