Developers Are All Doomed (?)

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

There's a phrase: "AI one-click."

Code that used to take a person days to write, AI whips up in mere seconds.

Ask an AI tool to build a login feature, and it produces plausible-looking code.

Ask it to fix this bug, and it offers a solution in an instant.

So will developers soon disappear?

This question left me uneasy.

What does a developer actually do?


In my view, a developer

is not someone who drives the latest trends with elegant, clean code

and builds great software.

That's not what a developer is.

A developer is someone who builds programs.

What is a program, then?

It's something that can automate and carry out some tedious task.

The dictionary defines it this way:

A set of instructions given to a computer, describing the method and order of processing

needed to solve a given problem.

To make a program is to solve a problem.

In other words, a developer is someone who solves problems.

So then, what is a "problem"?

Countless problems exist in this world.

Take, for example, the problem of hunger.

There are many actions one could take.

Eat bread, eat rice, order delivery... and so on.

Countless options exist.

Each action carries its own consequence.

Even "eating rice"

could mean eating a full bowl,

or eating just a spoonful...

— the options vary widely.

So what happens as a result of that choice?

Just as eating rice doesn't always mean you'll feel full,

the actions we take don't always solve the problem;

only the right choice yields the result we want.

"Put in such-and-such input, and you get such-and-such result" —

this correspondence is exactly what we call a problem (Problem).

If we express this using the concept of a "set," which we learn in middle school math:

eat bread -> hunger is solved.

eat bread -> hunger is not solved.

We can form pairs like these.

In this way, a problem can be defined as a pair relating a choice to its outcome.

In other words, a problem (Problem) can be defined as the relation between a set of inputs (Inputs) and a set of outputs (Solutions).

When we say we're "solving a problem,"

what we're really doing is finding the correspondence between input I and output S.

Expressed mathematically,

a problem can be represented as the following binary relation:

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

Here, P contains only the combinations of possible inputs and outputs that are actually "meaningful."

That is, input i corresponds to output s, and the meaning implied by this notation is

that we only regard as a "problem" the cases where a choice and its result are meaningfully connected.


But as in the example above, when the dimensions of the input and output sets grow too large,

it becomes hard to grasp the structure of the relation.

To reduce this complexity and make the discussion more rigorous,

let's simplify the output set and define it as follows:

S := { true, false }

This is like setting a kind of control variable.

Now we can restrict every problem to "the problem of judging whether something is true or false given an input."

In other words, it's about determining "does the given input satisfy some condition?"

This kind of problem is called a Decision Problem.

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

Through this relation, we can now express it as a function pair with a domain and a range.

This has the same structure as the general concept of a problem defined earlier,

but by reducing the output dimension to "true/false,"

it becomes a simpler, more mathematically tractable form of the problem.

This is how we formalized the problem.

So then, why, exactly,

did we go to the trouble of schematizing it this way?


The mathematician Alan Turing asked exactly this question.

If something exists that solves problems, how might it think and compute?

To answer this question, he completely redefined the very concept of "Computation."

While people focused on solving mathematical problems,

Turing focused instead on the "act" of solving a problem,

proposing an entirely new meta-level framework.

In other words, he set out to model the act itself of a thinking being performing computation.

He observed a mathematician writing symbols on paper,

applying rules sequentially, step by step,

and supposed that this behavior could be expressed mechanically.

That is how the Turing Machine came to be.

Turing broke down the human act of computation into three simplest elements.

  1. Tape: a paper tape divided into cells of fixed size. Each cell holds a symbol, and the tape can extend infinitely in length.

  2. Head: a head that can read one specific cell on the tape. It can move — or alternatively, the head stays fixed and the tape moves.

  3. State register: a device that records the Turing machine's current state.

The machine reads one cell on the tape,

and according to the rules, writes a new symbol or moves one cell left or right.

Remarkably, by repeating just this simple process, it can express almost every computation we can imagine.

With a simple machine made up of just these three elements,

Turing proved the essential nature of the computation that every modern computer can perform.

If the answer to some problem

can be computed by a Turing machine in finite time,

then that problem was considered Computable.

In other words, being computable means the problem can be solved by a well-defined procedure (Algorithm).

Thanks to Turing's proof, unfortunately,

we now find ourselves doing the labor called coding.


Earlier, I said the Turing machine can express almost every computation.

"Almost" every one? Why did Turing say "almost"?

No matter how fast an algorithm you write,

no matter how much you raise its efficiency,

what if there exists a problem that simply cannot be solved to begin with?

Turing started from precisely this question.

Given a program and an input, will the program eventually halt — or run forever?

This is exactly what's called the Halting Problem.

At a glance it looks simple. But it isn't.

It's a problem that's surprisingly hard to answer with a simple "it halts" or "it doesn't halt."

But Turing arrived at a stunning conclusion.

No algorithm can determine, for every program, whether it halts or not.

This isn't a yes-or-no answer — it's a conclusion that transcends the question itself.

Turing made the following assumption.

Suppose a perfect "halting detector" exists that can judge whether any program halts.

Now, build a new program that takes that detector as input.

This program is designed to act in the opposite way to whatever the detector concludes.

If the input is judged to "halt," it keeps running;

if the input is judged "not to halt," it stops immediately.

# Assume: a perfect halting detector H(program, input)
# H(program, input) → True  : program halts
# H(program, input) → False : program does not halt

def HaltingParadox(program):
    if H(program, program) == True:
        while True: pass   # infinite loop
    else:
        return "Halt"

But the moment this program takes itself as input,

something strange happens.

HaltingParadox(HaltingParadox)

If it's predicted to "halt," it must keep running,

and if it's predicted "not to halt," it stops immediately.

Whichever judgment is made, the result is a contradiction.

Therefore, the very assumption that a "halting detector" exists cannot hold.

"I am a liar" ← is this sentence true or false?

In this way, Turing's method of proof is close to a paradox.

Simple, yet trapped in an inescapable self-contradiction,

it exposed the boundary separating what is computable from what is not.

Through this simple paradox, he showed the absolute limits of computation,

and concluded that not every problem is Computable.

This is what we call Non-computability.

Turing's halting problem revealed what cannot be computed —

that is, a limit that even the most brilliant algorithm can never reach.

This proof,

even though it cannot solve every problem,

is the mathematical definition of a model

that can still solve almost every problem.

Even though this paradox revealed the upper bound of what's Computable,

it doesn't mean every problem is uncomputable.

Most problems, given enough time and the right algorithm,

belong to a world that a Turing machine can fully solve.


However, saying something is computable

never meant it could always be solved within a feasible amount of time.

Some problems yield an answer right away,

while others are unimaginably slow.

How much the computation time grows as the input gets larger

is called "Time Complexity," expressed as something like O(n).

Modern people care less about whether a program works at all

and more about how fast and efficiently it runs.

Don't we get angrier at a program that runs slowly than one that doesn't run at all?

Even in games, this time complexity matters enormously.

The keyword you'll most often find in reviews is probably "optimization."

It's not enough for a game to merely run;

the rule of this business is that it has to run

smoothly, without lag, "well."

So for powerless developers like me, what matters

isn't building a program that works,

but building one that's more efficient and more effective.


One day, the village elder gathered the local youths and posed this problem:

There are 100 balls in a room.

They're all the same size, but exactly one "fake ball" is made of a different material and is heavier.

Find the fake ball among them.

This problem doesn't look impossible.

It just takes some time — with the right method, anyone can find the answer.

As the elder quietly watched,

the youths were each solving the problem in their own way.

  1. The Old-School Bill Gates Type

Weigh every single ball one at a time, and pick the heaviest one.

It takes 100 computations, but it's a sure method.

Very honest young men — they'll make fine, hardworking members of the village.

  1. The Their-Own-League Type

Split the balls in half, place them on a balance scale,

keep only the heavier side, and split it in half again.

Repeating this process finds the answer in roughly log₂100 ≈ 7 computations.

Efficient.

  1. The Google-Interview-Question Type

Arrange all the balls on a slope

and roll them at the same time to see which one arrives first.

Only a single computation is needed.

These are people who love solving Google interview questions they find online — at a glance, they look like geniuses.

(Though, come to think of it, I've never heard of any of them actually getting hired at Google.)

All three methods share a procedure that can solve the problem in Polynomial time.

In other words, the correct answer can be directly computed for a given input,

and that computation finishes within a time predictable in proportion to the input size.

To put it a bit more technically,

these are problems where both Search and Verification can be performed in polynomial time.

The set of problems with this property is defined as the class P (Polynomial time solvable).


The elder, just by placing the balls the youths brought back on the scale once,

can immediately confirm whether their claim is correct.

Compared to the process of finding the answer, verification is very simple.

Let's pause here and focus for a moment on this idea of "verification."

You shouldn't do this, but suppose you found a stranger's bankbook.

Checking whether the PIN you entered into an ATM is correct or not is easy,

but finding that bankbook's PIN in the first place is extremely hard.

To put it a bit more technically,

Verification is possible in Polynomial time,

but Search can be far more complex than that.

In this way, some problems are quick to verify

but far more complex to actually solve.

These problems carry a difficulty that is verifiable,

and we call them NP (Non-deterministic Polynomial time) problems.


Now we can finally split the "problem" we've been discussing

into P problems and NP problems.

At first glance, these two categories of problems look clearly distinct.

But look closely, and they turn out to be oddly similar.

P problems are ones where you can find the answer quickly,

while NP problems are ones where, given an answer, you can verify it quickly.

Both are alike in that they can accomplish something within polynomial time.

It's just that one is the ability to compute a solution directly,

while the other is the ability to judge the correctness of an already-given solution.

So then, are these two really different things?

If a problem's answer can be verified quickly,

shouldn't there eventually exist a way to find that answer quickly too?

This simple but fundamental question is exactly

what leads to the P vs NP problem.

Come to think of it, this resembles the human thought process.

It takes us a long time to come up with something,

but we judge relatively quickly whether someone else's answer is correct.

In other words, creation is hard, but criticism is easy.

Making something is NP-like; evaluating it is P-like.

This isn't merely a story about mathematics.

Can artificial intelligence create art?

Can human creativity be reduced to computation?

All these questions live in the shadow of P vs NP.

Modern cryptography stands on NP-hard problems.

Verification is fast, but decryption is a structure that's unrealistically slow.

RSA, blockchain, digital signatures — all the same.

If P = NP,

every secret in the world would disappear.

Encryption would be broken instantly, security would collapse,

and even artistic creativity could be reduced to a formula, just like the phrase "AI one-click."

Conversely, if P ≠ NP,

the world remains a little imperfect, but beautiful in its own way.

Because it can't be solved, people will keep striving to find the answer.

That's why this question —

"Is the set P equal to the set NP?" —

was chosen by the Clay Mathematics Institute as one of the Millennium Prize Problems.

A prize of one million dollars awaits whoever presents a clear proof.

But over the past several decades,

no one has completed that proof.

Nor has AI one-click managed to solve it either.

Whether the two are equal or not is, in itself, unknowable — for now.


Anyway, back to the point.

AI is a being that solves problems faster than any machine humans have ever made.

It takes in countless inputs and produces an answer in mere seconds.

Astonishingly accurate, and at times it even appears more creative than a human.

Is it any wonder the phrase "AI one-click" came about?

But even that creativity actually operates along a predictable path.

AI runs across a graph of countless possibilities,

choosing, at every point, the path with the highest score.

That's how it was with Go.

Even the world of Go, which once seemed unconquerable,

fell not because AlphaGo calculated every possible move,

but because it found the next move with the highest win probability.

That wasn't the result of exploring every possible solution,

but the result of statistically selecting the most plausible one.

ChatGPT is the same.

Across an infinite graph of sentences,

it computes the probability of the next word

and picks the word with the highest probability among them.

For example,

given the sentence "I was hungry, so"

the AI searches for the word that comes next.

Say, if it were [ I - was hungry - so - I ate - ramen ],

that's a frequently used combination, so its probability is high.

On the other hand, if it were [ I - was hungry - so - I closed - the window ],

this sentence is just less frequently used, so its probability is low —

it isn't judged to be semantically wrong.

When we hear the two sentences,

we intuitively tell which one makes sense and which is nonsense,

but AI is different — it's ultimately just the result of a probability calculation.

Like an algorithm simply following a path.

All of this, in the end, happens within the world of P problems.

If you ask for the fastest route from your house to Seoul,

AI will find it faster than anyone.

But it doesn't know what that route means.

It merely finds the fastest, most efficient path

within the given conditions.

No reason, no meaning.

AI computes quickly and decides quickly.

But that's all it does.

If you ask AlphaGo why it placed a stone there,

the answer is just "because it had the highest win rate" — nothing more.

In Go, there's no such thing as "just because." When you want to place a stone, there has to be a thought or a plan behind what you're trying to do with that move. That's what we call "intent."

And when I'm trying to do something, I also have to figure out what the other side is thinking and planning. That's called reading the opponent's "intentions."

Being able to explain why you placed a stone there means, in the end, that you understand how you read your opponent, and how sharp your assessment of the board really was.

A move played "just because" is a move played by "chance," and you learn nothing from it whether you win or lose. "Chance" isn't something you wait for — it's a gift that comes to someone who has already finished preparing.

— from Misaeng

But in NP-hard problems —

that is, in a world where you can't even efficiently know whether an answer exists —

AI still comes to a halt, standing right alongside humans.

What we often call "AI omnipotence"

feels like an illusion built right on top of this boundary.

AI can be a tool that solves problems,

but it isn't a being that finds the meaning of a problem.

It only finds the most efficient path;

it cannot, on its own, know what meaning that path carries.

That's still the domain of humans.

So the question of P vs NP

is perhaps an even more fundamental question in an age like this one, the age of AI.

The moment we believe AI can solve every problem,

we'll start trying to compute even the questions we ought to be asking.

In that world of uncertainty, creativity, and contradiction,

humans still stand.

Not everything verifiable is necessarily solvable,

and not everything computable is necessarily understandable.

Perhaps it's thanks to this very imperfection

that we remain beings still capable of thought.

Maybe we can still make a living, after all.

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

댓글 0